The OpenD Programming Language

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     @(imported!"core.attribute".mutableRefInit) 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     static if (isCopyable!T)
3260         this(inout T value) inout
3261         {
3262             _value.payload = value;
3263             _isNull = false;
3264         }
3265     else
3266         this(T value) inout
3267         {
3268             import std.algorithm.mutation : move;
3269             _value.payload = move(value);
3270             _isNull = false;
3271         }
3272 
3273     static if (hasElaborateDestructor!T)
3274     {
3275         ~this()
3276         {
3277             if (!_isNull)
3278             {
3279                 destroy(_value.payload);
3280             }
3281         }
3282     }
3283 
3284     static if (!isCopyable!T)
3285         @disable this(this);
3286     else
3287     static if (__traits(hasPostblit, T))
3288     {
3289         this(this)
3290         {
3291             if (!_isNull)
3292                 _value.payload.__xpostblit();
3293         }
3294     }
3295     else static if (__traits(hasCopyConstructor, T))
3296     {
3297         this(ref return scope inout Nullable!T rhs) inout
3298         {
3299             _isNull = rhs._isNull;
3300             if (!_isNull)
3301                 _value.payload = rhs._value.payload;
3302             else
3303                 _value = DontCallDestructorT.init;
3304         }
3305     }
3306 
3307     /**
3308      * If they are both null, then they are equal. If one is null and the other
3309      * is not, then they are not equal. If they are both non-null, then they are
3310      * equal if their values are equal.
3311      */
3312     bool opEquals(this This, Rhs)(auto ref Rhs rhs)
3313     if (!is(CommonType!(This, Rhs) == void))
3314     {
3315         static if (is(This == Rhs))
3316         {
3317             if (_isNull)
3318                 return rhs._isNull;
3319             if (rhs._isNull)
3320                 return false;
3321             return _value.payload == rhs._value.payload;
3322         }
3323         else
3324         {
3325             alias Common = CommonType!(This, Rhs);
3326             return cast(Common) this == cast(Common) rhs;
3327         }
3328     }
3329 
3330     /// Ditto
3331     bool opEquals(this This, Rhs)(auto ref Rhs rhs)
3332     if (is(CommonType!(This, Rhs) == void) && is(typeof(this.get == rhs)))
3333     {
3334         return _isNull ? false : rhs == _value.payload;
3335     }
3336 
3337     ///
3338     @safe unittest
3339     {
3340         Nullable!int empty;
3341         Nullable!int a = 42;
3342         Nullable!int b = 42;
3343         Nullable!int c = 27;
3344 
3345         assert(empty == empty);
3346         assert(empty == Nullable!int.init);
3347         assert(empty != a);
3348         assert(empty != b);
3349         assert(empty != c);
3350 
3351         assert(a == b);
3352         assert(a != c);
3353 
3354         assert(empty != 42);
3355         assert(a == 42);
3356         assert(c != 42);
3357     }
3358 
3359     @safe unittest
3360     {
3361         // Test constness
3362         immutable Nullable!int a = 42;
3363         Nullable!int b = 42;
3364         immutable Nullable!int c = 29;
3365         Nullable!int d = 29;
3366         immutable e = 42;
3367         int f = 29;
3368         assert(a == a);
3369         assert(a == b);
3370         assert(a != c);
3371         assert(a != d);
3372         assert(a == e);
3373         assert(a != f);
3374 
3375         // Test rvalue
3376         assert(a == const Nullable!int(42));
3377         assert(a != Nullable!int(29));
3378     }
3379 
3380     // https://issues.dlang.org/show_bug.cgi?id=17482
3381     @system unittest
3382     {
3383         import std.variant : Variant;
3384         Nullable!Variant a = Variant(12);
3385         assert(a == 12);
3386         Nullable!Variant e;
3387         assert(e != 12);
3388     }
3389 
3390     size_t toHash() const @safe nothrow
3391     {
3392         static if (__traits(compiles, .hashOf(_value.payload)))
3393             return _isNull ? 0 : .hashOf(_value.payload);
3394         else
3395             // Workaround for when .hashOf is not both @safe and nothrow.
3396             return _isNull ? 0 : typeid(T).getHash(&_value.payload);
3397     }
3398 
3399     /**
3400      * Gives the string `"Nullable.null"` if `isNull` is `true`. Otherwise, the
3401      * result is equivalent to calling $(REF formattedWrite, std,format) on the
3402      * underlying value.
3403      *
3404      * Params:
3405      *     writer = A `char` accepting
3406      *     $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
3407      *     fmt = A $(REF FormatSpec, std,format) which is used to represent
3408      *     the value if this Nullable is not null
3409      * Returns:
3410      *     A `string` if `writer` and `fmt` are not set; `void` otherwise.
3411      */
3412     string toString()
3413     {
3414         import std.array : appender;
3415         auto app = appender!string();
3416         auto spec = singleSpec("%s");
3417         toString(app, spec);
3418         return app.data;
3419     }
3420 
3421     /// ditto
3422     string toString() const
3423     {
3424         import std.array : appender;
3425         auto app = appender!string();
3426         auto spec = singleSpec("%s");
3427         toString(app, spec);
3428         return app.data;
3429     }
3430 
3431     /// ditto
3432     void toString(W)(ref W writer, scope const ref FormatSpec!char fmt)
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     /// ditto
3443     void toString(W)(ref W writer, scope const ref FormatSpec!char fmt) const
3444     if (isOutputRange!(W, char))
3445     {
3446         import std.range.primitives : put;
3447         if (isNull)
3448             put(writer, "Nullable.null");
3449         else
3450             formatValue(writer, _value.payload, fmt);
3451     }
3452 
3453     /**
3454      * Check if `this` is in the null state.
3455      *
3456      * Returns:
3457      *     true $(B iff) `this` is in the null state, otherwise false.
3458      */
3459     @property bool isNull() const @safe pure nothrow
3460     {
3461         return _isNull;
3462     }
3463 
3464     ///
3465     @safe unittest
3466     {
3467         Nullable!int ni;
3468         assert(ni.isNull);
3469 
3470         ni = 0;
3471         assert(!ni.isNull);
3472     }
3473 
3474     // https://issues.dlang.org/show_bug.cgi?id=14940
3475     @safe unittest
3476     {
3477         import std.array : appender;
3478         import std.format.write : formattedWrite;
3479 
3480         auto app = appender!string();
3481         Nullable!int a = 1;
3482         formattedWrite(app, "%s", a);
3483         assert(app.data == "1");
3484     }
3485 
3486     // https://issues.dlang.org/show_bug.cgi?id=19799
3487     @safe unittest
3488     {
3489         import std.format : format;
3490 
3491         const Nullable!string a = const(Nullable!string)();
3492 
3493         format!"%s"(a);
3494     }
3495 
3496     /**
3497      * Forces `this` to the null state.
3498      */
3499     void nullify()()
3500     {
3501         static if (is(T == class) || is(T == interface))
3502             _value.payload = null;
3503         else
3504             .destroy(_value.payload);
3505         _isNull = true;
3506     }
3507 
3508     ///
3509     @safe unittest
3510     {
3511         Nullable!int ni = 0;
3512         assert(!ni.isNull);
3513 
3514         ni.nullify();
3515         assert(ni.isNull);
3516     }
3517 
3518     /**
3519      * Assigns `value` to the internally-held state. If the assignment
3520      * succeeds, `this` becomes non-null.
3521      *
3522      * Params:
3523      *     value = A value of type `T` to assign to this `Nullable`.
3524      */
3525     ref Nullable opAssign()(T value) return
3526     {
3527         import std.algorithm.mutation : moveEmplace, move;
3528 
3529         if (_isNull)
3530         {
3531             // trusted since payload is known to be uninitialized.
3532             () @trusted { moveEmplace(value, _value.payload); }();
3533         }
3534         else
3535         {
3536             move(value, _value.payload);
3537         }
3538         _isNull = false;
3539         return this;
3540     }
3541 
3542     /**
3543      * If this `Nullable` wraps a type that already has a null value
3544      * (such as a pointer), then assigning the null value to this
3545      * `Nullable` is no different than assigning any other value of
3546      * type `T`, and the resulting code will look very strange. It
3547      * is strongly recommended that this be avoided by instead using
3548      * the version of `Nullable` that takes an additional `nullValue`
3549      * template argument.
3550      */
3551     @safe unittest
3552     {
3553         //Passes
3554         Nullable!(int*) npi;
3555         assert(npi.isNull);
3556 
3557         //Passes?!
3558         npi = null;
3559         assert(!npi.isNull);
3560     }
3561 
3562     /**
3563      * Gets the value if not null. If `this` is in the null state, and the optional
3564      * parameter `fallback` was provided, it will be returned. Without `fallback`,
3565      * calling `get` with a null state is invalid.
3566      *
3567      * When the fallback type is different from the Nullable type, `get(T)` returns
3568      * the common type.
3569      *
3570      * Params:
3571      *     fallback = the value to return in case the `Nullable` is null.
3572      *
3573      * Returns:
3574      *     The value held internally by this `Nullable`.
3575      */
3576     @property ref inout(T) get() inout @safe pure nothrow
3577     {
3578         enum message = "Called `get' on null Nullable!" ~ T.stringof ~ ".";
3579         assert(!isNull, message);
3580         return _value.payload;
3581     }
3582 
3583     /// ditto
3584     @property inout(T) get()(inout(T) fallback) inout
3585     {
3586         return isNull ? fallback : _value.payload;
3587     }
3588 
3589     /// ditto
3590     @property auto get(U)(inout(U) fallback) inout
3591     {
3592         return isNull ? fallback : _value.payload;
3593     }
3594 
3595     /// $(MREF_ALTTEXT Range interface, std, range, primitives) functions.
3596     alias empty = isNull;
3597 
3598     /// ditto
3599     alias popFront = nullify;
3600 
3601     /// ditto
3602     alias popBack = nullify;
3603 
3604     /// ditto
3605     @property ref inout(T) front() inout @safe pure nothrow
3606     {
3607         return get();
3608     }
3609 
3610     /// ditto
3611     alias back = front;
3612 
3613     /// ditto
3614     static if (isCopyable!T)
3615     @property inout(typeof(this)) save() inout
3616     {
3617         return this;
3618     }
3619 
3620     /// ditto
3621     static if (isCopyable!T)
3622     inout(typeof(this)) opIndex(size_t[2] dim) inout
3623     in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3624     {
3625         return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3626     }
3627     /// ditto
3628     size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3629     {
3630         return [from, to];
3631     }
3632 
3633     /// ditto
3634     @property size_t length() const @safe pure nothrow
3635     {
3636         return !empty;
3637     }
3638 
3639     /// ditto
3640     alias opDollar(size_t dim : 0) = length;
3641 
3642     /// ditto
3643     ref inout(T) opIndex(size_t index) inout @safe pure nothrow
3644     in (index < length)
3645     {
3646         return get();
3647     }
3648 
3649     /**
3650      * Converts `Nullable` to a range. Works even when the contained type is `immutable`.
3651      */
3652     auto opSlice(this This)()
3653     {
3654         static struct NullableRange
3655         {
3656             private This value;
3657 
3658             // starts out true if value is null
3659             private bool empty_;
3660 
3661             @property bool empty() const @safe pure nothrow
3662             {
3663                 return empty_;
3664             }
3665 
3666             void popFront() @safe pure nothrow
3667             {
3668                 empty_ = true;
3669             }
3670 
3671             alias popBack = popFront;
3672 
3673             @property ref inout(typeof(value.get())) front() inout @safe pure nothrow
3674             {
3675                 return value.get();
3676             }
3677 
3678             alias back = front;
3679 
3680             @property inout(typeof(this)) save() inout
3681             {
3682                 return this;
3683             }
3684 
3685             size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3686             {
3687                 return [from, to];
3688             }
3689 
3690             @property size_t length() const @safe pure nothrow
3691             {
3692                 return !empty;
3693             }
3694 
3695             alias opDollar(size_t dim : 0) = length;
3696 
3697             ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow
3698             in (index < length)
3699             {
3700                 return value.get();
3701             }
3702 
3703             inout(typeof(this)) opIndex(size_t[2] dim) inout
3704             in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3705             {
3706                 return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3707             }
3708 
3709             auto opIndex() inout
3710             {
3711                 return this;
3712             }
3713         }
3714         return NullableRange(this, isNull);
3715     }
3716 }
3717 
3718 /// ditto
3719 auto nullable(T)(T t)
3720 {
3721     return Nullable!T(t);
3722 }
3723 
3724 ///
3725 @safe unittest
3726 {
3727     struct CustomerRecord
3728     {
3729         string name;
3730         string address;
3731         int customerNum;
3732     }
3733 
3734     Nullable!CustomerRecord getByName(string name)
3735     {
3736         //A bunch of hairy stuff
3737 
3738         return Nullable!CustomerRecord.init;
3739     }
3740 
3741     auto queryResult = getByName("Doe, John");
3742     if (!queryResult.isNull)
3743     {
3744         //Process Mr. Doe's customer record
3745         auto address = queryResult.get.address;
3746         auto customerNum = queryResult.get.customerNum;
3747 
3748         //Do some things with this customer's info
3749     }
3750     else
3751     {
3752         //Add the customer to the database
3753     }
3754 }
3755 
3756 ///
3757 @system unittest
3758 {
3759     import std.exception : assertThrown;
3760 
3761     auto a = 42.nullable;
3762     assert(!a.isNull);
3763     assert(a.get == 42);
3764 
3765     a.nullify();
3766     assert(a.isNull);
3767     assertThrown!Throwable(a.get);
3768 }
3769 ///
3770 @safe unittest
3771 {
3772     import std.algorithm.iteration : each, joiner;
3773     Nullable!int a = 42;
3774     Nullable!int b;
3775     // Add each value to an array
3776     int[] arr;
3777     a.each!((n) => arr ~= n);
3778     assert(arr == [42]);
3779     b.each!((n) => arr ~= n);
3780     assert(arr == [42]);
3781     // Take first value from an array of Nullables
3782     Nullable!int[] c = new Nullable!int[](10);
3783     c[7] = Nullable!int(42);
3784     assert(c.joiner.front == 42);
3785 }
3786 @safe unittest
3787 {
3788     auto k = Nullable!int(74);
3789     assert(k == 74);
3790     k.nullify();
3791     assert(k.isNull);
3792 }
3793 @safe unittest
3794 {
3795     static int f(scope const Nullable!int x) {
3796         return x.isNull ? 42 : x.get;
3797     }
3798     Nullable!int a;
3799     assert(f(a) == 42);
3800     a = 8;
3801     assert(f(a) == 8);
3802     a.nullify();
3803     assert(f(a) == 42);
3804 }
3805 @system unittest
3806 {
3807     import std.exception : assertThrown;
3808 
3809     static struct S { int x; }
3810     Nullable!S s;
3811     assert(s.isNull);
3812     s = S(6);
3813     assert(s == S(6));
3814     assert(s != S(0));
3815     assert(s.get != S(0));
3816     s.get.x = 9190;
3817     assert(s.get.x == 9190);
3818     s.nullify();
3819     assertThrown!Throwable(s.get.x = 9441);
3820 }
3821 @safe unittest
3822 {
3823     // Ensure Nullable can be used in pure/nothrow/@safe environment.
3824     function() @safe pure nothrow
3825     {
3826         Nullable!int n;
3827         assert(n.isNull);
3828         n = 4;
3829         assert(!n.isNull);
3830         assert(n == 4);
3831         n.nullify();
3832         assert(n.isNull);
3833     }();
3834 }
3835 @system unittest
3836 {
3837     // Ensure Nullable can be used when the value is not pure/nothrow/@safe
3838     static struct S
3839     {
3840         int x;
3841         this(this) @system {}
3842     }
3843 
3844     Nullable!S s;
3845     assert(s.isNull);
3846     s = S(5);
3847     assert(!s.isNull);
3848     assert(s.get.x == 5);
3849     s.nullify();
3850     assert(s.isNull);
3851 }
3852 
3853 // https://issues.dlang.org/show_bug.cgi?id=9404
3854 @safe unittest
3855 {
3856     alias N = Nullable!int;
3857 
3858     void foo(N a)
3859     {
3860         N b;
3861         b = a; // `N b = a;` works fine
3862     }
3863     N n;
3864     foo(n);
3865 }
3866 @safe unittest
3867 {
3868     //Check nullable immutable is constructable
3869     {
3870         auto a1 = Nullable!(immutable int)();
3871         auto a2 = Nullable!(immutable int)(1);
3872         auto i = a2.get;
3873     }
3874     //Check immutable nullable is constructable
3875     {
3876         auto a1 = immutable (Nullable!int)();
3877         auto a2 = immutable (Nullable!int)(1);
3878         auto i = a2.get;
3879     }
3880 }
3881 @safe unittest
3882 {
3883     alias NInt   = Nullable!int;
3884 
3885     //Construct tests
3886     {
3887         //from other Nullable null
3888         NInt a1;
3889         NInt b1 = a1;
3890         assert(b1.isNull);
3891 
3892         //from other Nullable non-null
3893         NInt a2 = NInt(1);
3894         NInt b2 = a2;
3895         assert(b2 == 1);
3896 
3897         //Construct from similar nullable
3898         auto a3 = immutable(NInt)();
3899         NInt b3 = a3;
3900         assert(b3.isNull);
3901     }
3902 
3903     //Assign tests
3904     {
3905         //from other Nullable null
3906         NInt a1;
3907         NInt b1;
3908         b1 = a1;
3909         assert(b1.isNull);
3910 
3911         //from other Nullable non-null
3912         NInt a2 = NInt(1);
3913         NInt b2;
3914         b2 = a2;
3915         assert(b2 == 1);
3916 
3917         //Construct from similar nullable
3918         auto a3 = immutable(NInt)();
3919         NInt b3 = a3;
3920         b3 = a3;
3921         assert(b3.isNull);
3922     }
3923 }
3924 @safe unittest
3925 {
3926     //Check nullable is nicelly embedable in a struct
3927     static struct S1
3928     {
3929         Nullable!int ni;
3930     }
3931     static struct S2 //inspired from 9404
3932     {
3933         Nullable!int ni;
3934         this(ref S2 other)
3935         {
3936             ni = other.ni;
3937         }
3938         void opAssign(ref S2 other)
3939         {
3940             ni = other.ni;
3941         }
3942     }
3943     static foreach (S; AliasSeq!(S1, S2))
3944     {{
3945         S a;
3946         S b = a;
3947         S c;
3948         c = a;
3949     }}
3950 }
3951 
3952 // https://issues.dlang.org/show_bug.cgi?id=10268
3953 @system unittest
3954 {
3955     import std.json;
3956     JSONValue value = null;
3957     auto na = Nullable!JSONValue(value);
3958 
3959     struct S1 { int val; }
3960     struct S2 { int* val; }
3961     struct S3 { immutable int* val; }
3962 
3963     {
3964         auto sm = S1(1);
3965         immutable si = immutable S1(1);
3966         auto x1 =           Nullable!S1(sm);
3967         auto x2 = immutable Nullable!S1(sm);
3968         auto x3 =           Nullable!S1(si);
3969         auto x4 = immutable Nullable!S1(si);
3970         assert(x1.get.val == 1);
3971         assert(x2.get.val == 1);
3972         assert(x3.get.val == 1);
3973         assert(x4.get.val == 1);
3974     }
3975 
3976     auto nm = 10;
3977     immutable ni = 10;
3978 
3979     {
3980         auto sm = S2(&nm);
3981         immutable si = immutable S2(&ni);
3982         auto x1 =           Nullable!S2(sm);
3983         static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
3984         static assert(!__traits(compiles, { auto x3 =           Nullable!S2(si); }));
3985         auto x4 = immutable Nullable!S2(si);
3986         assert(*x1.get.val == 10);
3987         assert(*x4.get.val == 10);
3988     }
3989 
3990     {
3991         auto sm = S3(&ni);
3992         immutable si = immutable S3(&ni);
3993         auto x1 =           Nullable!S3(sm);
3994         auto x2 = immutable Nullable!S3(sm);
3995         auto x3 =           Nullable!S3(si);
3996         auto x4 = immutable Nullable!S3(si);
3997         assert(*x1.get.val == 10);
3998         assert(*x2.get.val == 10);
3999         assert(*x3.get.val == 10);
4000         assert(*x4.get.val == 10);
4001     }
4002 }
4003 
4004 // https://issues.dlang.org/show_bug.cgi?id=10357
4005 @safe unittest
4006 {
4007     import std.datetime;
4008     Nullable!SysTime time = SysTime(0);
4009 }
4010 
4011 // https://issues.dlang.org/show_bug.cgi?id=10915
4012 @system unittest
4013 {
4014     import std.conv : to;
4015     import std.array;
4016 
4017     Appender!string buffer;
4018 
4019     Nullable!int ni;
4020     assert(ni.to!string() == "Nullable.null");
4021     assert((cast(const) ni).to!string() == "Nullable.null");
4022 
4023     struct Test { string s; }
4024     alias NullableTest = Nullable!Test;
4025 
4026     NullableTest nt = Test("test");
4027     // test output range version
4028     assert(nt.to!string() == `Test("test")`);
4029     // test appender version
4030     assert(nt.toString() == `Test("test")`);
4031     // test const version
4032     assert((cast(const) nt).toString() == `const(Test)("test")`);
4033 
4034     NullableTest ntn = Test("null");
4035     assert(ntn.to!string() == `Test("null")`);
4036 
4037     class TestToString
4038     {
4039         double d;
4040 
4041         this (double d)
4042         {
4043             this.d = d;
4044         }
4045 
4046         override string toString()
4047         {
4048             return d.to!string();
4049         }
4050     }
4051     Nullable!TestToString ntts = new TestToString(2.5);
4052     assert(ntts.to!string() == "2.5");
4053 }
4054 
4055 // https://issues.dlang.org/show_bug.cgi?id=14477
4056 @safe unittest
4057 {
4058     static struct DisabledDefaultConstructor
4059     {
4060         @disable this();
4061         this(int i) { }
4062     }
4063     Nullable!DisabledDefaultConstructor var;
4064     var = DisabledDefaultConstructor(5);
4065     var.nullify;
4066 }
4067 
4068 // https://issues.dlang.org/show_bug.cgi?id=17440
4069 @system unittest
4070 {
4071     static interface I { }
4072 
4073     static class C : I
4074     {
4075         int canary;
4076         ~this()
4077         {
4078             canary = 0x5050DEAD;
4079         }
4080     }
4081     auto c = new C;
4082     c.canary = 0xA71FE;
4083     auto nc = nullable(c);
4084     nc.nullify;
4085     assert(c.canary == 0xA71FE);
4086 
4087     I i = c;
4088     auto ni = nullable(i);
4089     ni.nullify;
4090     assert(c.canary == 0xA71FE);
4091 }
4092 
4093 // https://issues.dlang.org/show_bug.cgi?id=19037
4094 @safe unittest
4095 {
4096     import std.datetime : SysTime;
4097 
4098     struct Test
4099     {
4100         SysTime _st;
4101 
4102         static bool destroyed;
4103 
4104         @disable this();
4105         this(int _dummy) {}
4106         ~this() @safe { destroyed = true; }
4107 
4108         // mustn't call opAssign on Test.init in Nullable!Test, because the invariant
4109         // will be called before opAssign on the Test.init that is in Nullable
4110         // and Test.init violates its invariant.
4111         void opAssign(Test rhs) @safe { assert(false); }
4112     }
4113 
4114     {
4115         Nullable!Test nt;
4116 
4117         nt = Test(1);
4118 
4119         // destroy value
4120         Test.destroyed = false;
4121 
4122         nt.nullify;
4123 
4124         assert(Test.destroyed);
4125 
4126         Test.destroyed = false;
4127     }
4128     // don't run destructor on T.init in Nullable on scope exit!
4129     assert(!Test.destroyed);
4130 }
4131 // check that the contained type's destructor is called on assignment
4132 @system unittest
4133 {
4134     struct S
4135     {
4136         // can't be static, since we need a specific value's pointer
4137         bool* destroyedRef;
4138 
4139         ~this()
4140         {
4141             if (this.destroyedRef)
4142             {
4143                 *this.destroyedRef = true;
4144             }
4145         }
4146     }
4147 
4148     Nullable!S ns;
4149 
4150     bool destroyed;
4151 
4152     ns = S(&destroyed);
4153 
4154     // reset from rvalue destruction in Nullable's opAssign
4155     destroyed = false;
4156 
4157     // overwrite Nullable
4158     ns = S(null);
4159 
4160     // the original S should be destroyed.
4161     assert(destroyed == true);
4162 }
4163 // check that the contained type's destructor is still called when required
4164 @system unittest
4165 {
4166     bool destructorCalled = false;
4167 
4168     struct S
4169     {
4170         bool* destroyed;
4171         ~this() { *this.destroyed = true; }
4172     }
4173 
4174     {
4175         Nullable!S ns;
4176     }
4177     assert(!destructorCalled);
4178     {
4179         Nullable!S ns = Nullable!S(S(&destructorCalled));
4180 
4181         destructorCalled = false; // reset after S was destroyed in the NS constructor
4182     }
4183     assert(destructorCalled);
4184 }
4185 
4186 // check that toHash on Nullable is forwarded to the contained type
4187 @system unittest
4188 {
4189     struct S
4190     {
4191         size_t toHash() const @safe pure nothrow { return 5; }
4192     }
4193 
4194     Nullable!S s1 = S();
4195     Nullable!S s2 = Nullable!S();
4196 
4197     assert(typeid(Nullable!S).getHash(&s1) == 5);
4198     assert(typeid(Nullable!S).getHash(&s2) == 0);
4199 }
4200 
4201 // https://issues.dlang.org/show_bug.cgi?id=21704
4202 @safe unittest
4203 {
4204     import std.array : staticArray;
4205 
4206     bool destroyed;
4207 
4208     struct Probe
4209     {
4210         ~this() { destroyed = true; }
4211     }
4212 
4213     {
4214         Nullable!(Probe[1]) test = [Probe()].staticArray;
4215         destroyed = false;
4216     }
4217     assert(destroyed);
4218 }
4219 
4220 // https://issues.dlang.org/show_bug.cgi?id=21705
4221 @safe unittest
4222 {
4223     static struct S
4224     {
4225         int n;
4226         bool opEquals(S rhs) { return n == rhs.n; }
4227     }
4228 
4229     Nullable!S test1 = S(1), test2 = S(1);
4230     S s = S(1);
4231 
4232     assert(test1 == s);
4233     assert(test1 == test2);
4234 }
4235 
4236 // https://issues.dlang.org/show_bug.cgi?id=22101
4237 @safe unittest
4238 {
4239     static int impure;
4240 
4241     struct S
4242     {
4243         ~this() { impure++; }
4244     }
4245 
4246     Nullable!S s;
4247     s.get(S());
4248 }
4249 
4250 // https://issues.dlang.org/show_bug.cgi?id=22100
4251 @safe unittest
4252 {
4253     Nullable!int a, b, c;
4254     a = b = c = 5;
4255     a = b = c = nullable(5);
4256 }
4257 
4258 // https://issues.dlang.org/show_bug.cgi?id=18374
4259 @safe pure nothrow unittest
4260 {
4261     import std.algorithm.comparison : equal;
4262     import std.range : only, takeNone;
4263     import std.range.primitives : hasAssignableElements, hasLength,
4264         hasLvalueElements, hasSlicing, hasSwappableElements,
4265         isRandomAccessRange;
4266     Nullable!int a = 42;
4267     assert(!a.empty);
4268     assert(a.front == 42);
4269     assert(a.back == 42);
4270     assert(a[0] == 42);
4271     assert(a.equal(only(42)));
4272     assert(a[0 .. $].equal(only(42)));
4273     a[0] = 43;
4274     assert(a.equal(only(43)));
4275     --a[0];
4276     assert(a.equal(only(42)));
4277     Nullable!int b;
4278     assert(b.empty);
4279     assert(b.equal(takeNone(b)));
4280     Nullable!int c = a.save();
4281     assert(!c.empty);
4282     c.popFront();
4283     assert(!a.empty);
4284     assert(c.empty);
4285 
4286     assert(isRandomAccessRange!(Nullable!int));
4287     assert(hasLength!(Nullable!int));
4288     assert(hasSlicing!(Nullable!int));
4289     assert(hasAssignableElements!(Nullable!int));
4290     assert(hasSwappableElements!(Nullable!int));
4291     assert(hasLvalueElements!(Nullable!int));
4292 }
4293 
4294 // https://issues.dlang.org/show_bug.cgi?id=23640
4295 @safe pure nothrow unittest
4296 {
4297     import std.algorithm.comparison : equal;
4298     import std.range : only;
4299     import std.range.primitives : hasLength, hasSlicing,
4300         isRandomAccessRange;
4301     static immutable struct S { int[] array; }
4302     auto value = S([42]);
4303     alias ImmutableNullable = immutable Nullable!S;
4304     auto a = ImmutableNullable(value)[];
4305     alias Range = typeof(a);
4306     assert(isRandomAccessRange!Range);
4307     assert(hasLength!Range);
4308     assert(hasSlicing!Range);
4309     assert(!a.empty);
4310     assert(a.front == value);
4311     assert(a.back == value);
4312     assert(a[0] == value);
4313     assert(a.equal(only(value)));
4314     assert(a[0 .. $].equal(only(value)));
4315     Range b = a.save();
4316     assert(!b.empty);
4317     b.popFront();
4318     assert(!a.empty);
4319     assert(b.empty);
4320 }
4321 
4322 /**
4323 Just like `Nullable!T`, except that the null state is defined as a
4324 particular value. For example, $(D Nullable!(uint, uint.max)) is an
4325 `uint` that sets aside the value `uint.max` to denote a null
4326 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
4327 Nullable!T) because it does not need to store an extra `bool`.
4328 
4329 Params:
4330     T = The wrapped type for which Nullable provides a null value.
4331 
4332     nullValue = The null value which denotes the null state of this
4333                 `Nullable`. Must be of type `T`.
4334  */
4335 struct Nullable(T, T nullValue)
4336 {
4337     private T _value = nullValue;
4338 
4339 /**
4340 Constructor initializing `this` with `value`.
4341 
4342 Params:
4343     value = The value to initialize this `Nullable` with.
4344  */
4345     this(T value)
4346     {
4347         _value = value;
4348     }
4349 
4350     template toString()
4351     {
4352         import std.format.spec : FormatSpec;
4353         import std.format.write : formatValue;
4354         // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4355         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4356         {
4357             if (isNull)
4358             {
4359                 sink.formatValue("Nullable.null", fmt);
4360             }
4361             else
4362             {
4363                 sink.formatValue(_value, fmt);
4364             }
4365         }
4366 
4367         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4368         {
4369             if (isNull)
4370             {
4371                 sink.formatValue("Nullable.null", fmt);
4372             }
4373             else
4374             {
4375                 sink.formatValue(_value, fmt);
4376             }
4377         }
4378     }
4379 
4380 @system unittest
4381 {
4382     import std.conv : to;
4383 
4384     const Nullable!(ulong, 0) x = 1;
4385     assert(x.to!string == "1");
4386 }
4387 
4388 /**
4389 Check if `this` is in the null state.
4390 
4391 Returns:
4392     true $(B iff) `this` is in the null state, otherwise false.
4393  */
4394     @property bool isNull() const
4395     {
4396         //Need to use 'is' if T is a nullable type and
4397         //nullValue is null, or it's a compiler error
4398         static if (is(CommonType!(T, typeof(null)) == T) && nullValue is null)
4399         {
4400             return _value is nullValue;
4401         }
4402         //Need to use 'is' if T is a float type
4403         //because NaN != NaN
4404         else static if (__traits(isFloating, T) || __traits(compiles, { static assert(!(nullValue == nullValue)); }))
4405         {
4406             return _value is nullValue;
4407         }
4408         else
4409         {
4410             return _value == nullValue;
4411         }
4412     }
4413 
4414 ///
4415 @safe unittest
4416 {
4417     Nullable!(int, -1) ni;
4418     //Initialized to "null" state
4419     assert(ni.isNull);
4420 
4421     ni = 0;
4422     assert(!ni.isNull);
4423 }
4424 
4425 @system unittest
4426 {
4427     assert(typeof(this).init.isNull, typeof(this).stringof ~
4428         ".isNull does not work correctly because " ~ T.stringof ~
4429         " has an == operator that is non-reflexive and could not be" ~
4430         " determined before runtime to be non-reflexive!");
4431 }
4432 
4433 // https://issues.dlang.org/show_bug.cgi?id=11135
4434 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed
4435 version (none) @system unittest
4436 {
4437     static foreach (T; AliasSeq!(float, double, real))
4438     {{
4439         Nullable!(T, T.init) nf;
4440         //Initialized to "null" state
4441         assert(nf.isNull);
4442         assert(nf is typeof(nf).init);
4443 
4444         nf = 0;
4445         assert(!nf.isNull);
4446 
4447         nf.nullify();
4448         assert(nf.isNull);
4449     }}
4450 }
4451 
4452 /**
4453 Forces `this` to the null state.
4454  */
4455     void nullify()()
4456     {
4457         _value = nullValue;
4458     }
4459 
4460 ///
4461 @safe unittest
4462 {
4463     Nullable!(int, -1) ni = 0;
4464     assert(!ni.isNull);
4465 
4466     ni = -1;
4467     assert(ni.isNull);
4468 }
4469 
4470 /**
4471 Assigns `value` to the internally-held state. If the assignment
4472 succeeds, `this` becomes non-null. No null checks are made. Note
4473 that the assignment may leave `this` in the null state.
4474 
4475 Params:
4476     value = A value of type `T` to assign to this `Nullable`.
4477             If it is `nullvalue`, then the internal state of
4478             this `Nullable` will be set to null.
4479  */
4480     void opAssign()(T value)
4481     {
4482         import std.algorithm.mutation : swap;
4483 
4484         swap(value, _value);
4485     }
4486 
4487 /**
4488     If this `Nullable` wraps a type that already has a null value
4489     (such as a pointer), and that null value is not given for
4490     `nullValue`, then assigning the null value to this `Nullable`
4491     is no different than assigning any other value of type `T`,
4492     and the resulting code will look very strange. It is strongly
4493     recommended that this be avoided by using `T`'s "built in"
4494     null value for `nullValue`.
4495  */
4496 @system unittest
4497 {
4498     //Passes
4499     enum nullVal = cast(int*) 0xCAFEBABE;
4500     Nullable!(int*, nullVal) npi;
4501     assert(npi.isNull);
4502 
4503     //Passes?!
4504     npi = null;
4505     assert(!npi.isNull);
4506 }
4507 
4508 /**
4509 Gets the value. `this` must not be in the null state.
4510 This function is also called for the implicit conversion to `T`.
4511 
4512 Preconditions: `isNull` must be `false`.
4513 Returns:
4514     The value held internally by this `Nullable`.
4515  */
4516     @property ref inout(T) get() inout
4517     {
4518         //@@@6169@@@: We avoid any call that might evaluate nullValue's %s,
4519         //Because it might messup get's purity and safety inference.
4520         enum message = "Called `get' on null Nullable!(" ~ T.stringof ~ ",nullValue).";
4521         assert(!isNull, message);
4522         return _value;
4523     }
4524 
4525 ///
4526 @system unittest
4527 {
4528     import std.exception : assertThrown, assertNotThrown;
4529 
4530     Nullable!(int, -1) ni;
4531     //`get` is implicitly called. Will throw
4532     //an error in non-release mode
4533     assertThrown!Throwable(ni == 0);
4534 
4535     ni = 0;
4536     assertNotThrown!Throwable(ni == 0);
4537 }
4538 
4539 /**
4540 Implicitly converts to `T`.
4541 `this` must not be in the null state.
4542  */
4543     alias get this;
4544 }
4545 
4546 /// ditto
4547 auto nullable(alias nullValue, T)(T t)
4548 if (is (typeof(nullValue) == T))
4549 {
4550     return Nullable!(T, nullValue)(t);
4551 }
4552 
4553 ///
4554 @safe unittest
4555 {
4556     Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
4557     {
4558         //Find the needle, returning -1 if not found
4559 
4560         return Nullable!(size_t, size_t.max).init;
4561     }
4562 
4563     void sendLunchInvite(string name)
4564     {
4565     }
4566 
4567     //It's safer than C...
4568     auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
4569     auto pos = indexOf(coworkers, "Bob");
4570     if (!pos.isNull)
4571     {
4572         //Send Bob an invitation to lunch
4573         sendLunchInvite(coworkers[pos]);
4574     }
4575     else
4576     {
4577         //Bob not found; report the error
4578     }
4579 
4580     //And there's no overhead
4581     static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
4582 }
4583 
4584 ///
4585 @system unittest
4586 {
4587     import std.exception : assertThrown;
4588 
4589     Nullable!(int, int.min) a;
4590     assert(a.isNull);
4591     assertThrown!Throwable(a.get);
4592     a = 5;
4593     assert(!a.isNull);
4594     assert(a == 5);
4595     static assert(a.sizeof == int.sizeof);
4596 }
4597 
4598 ///
4599 @safe unittest
4600 {
4601     auto a = nullable!(int.min)(8);
4602     assert(a == 8);
4603     a.nullify();
4604     assert(a.isNull);
4605 }
4606 
4607 @nogc nothrow pure @safe unittest
4608 {
4609     // https://issues.dlang.org/show_bug.cgi?id=19226
4610     // fully handle non-self-equal nullValue
4611     static struct Fraction
4612     {
4613         int denominator;
4614         bool isNaN() const
4615         {
4616             return denominator == 0;
4617         }
4618         bool opEquals(const Fraction rhs) const
4619         {
4620             return !isNaN && denominator == rhs.denominator;
4621         }
4622     }
4623     alias N = Nullable!(Fraction, Fraction.init);
4624     assert(N.init.isNull);
4625 }
4626 
4627 @safe unittest
4628 {
4629     static int f(scope const Nullable!(int, int.min) x) {
4630         return x.isNull ? 42 : x.get;
4631     }
4632     Nullable!(int, int.min) a;
4633     assert(f(a) == 42);
4634     a = 8;
4635     assert(f(a) == 8);
4636     a.nullify();
4637     assert(f(a) == 42);
4638 }
4639 @safe unittest
4640 {
4641     // Ensure Nullable can be used in pure/nothrow/@safe environment.
4642     function() @safe pure nothrow
4643     {
4644         Nullable!(int, int.min) n;
4645         assert(n.isNull);
4646         n = 4;
4647         assert(!n.isNull);
4648         assert(n == 4);
4649         n.nullify();
4650         assert(n.isNull);
4651     }();
4652 }
4653 @system unittest
4654 {
4655     // Ensure Nullable can be used when the value is not pure/nothrow/@system
4656     static struct S
4657     {
4658         int x;
4659         bool opEquals(const S s) const @system { return s.x == x; }
4660     }
4661 
4662     Nullable!(S, S(711)) s;
4663     assert(s.isNull);
4664     s = S(5);
4665     assert(!s.isNull);
4666     assert(s.x == 5);
4667     s.nullify();
4668     assert(s.isNull);
4669 }
4670 @safe unittest
4671 {
4672     //Check nullable is nicelly embedable in a struct
4673     static struct S1
4674     {
4675         Nullable!(int, 0) ni;
4676     }
4677     static struct S2 //inspired from 9404
4678     {
4679         Nullable!(int, 0) ni;
4680         this(S2 other)
4681         {
4682             ni = other.ni;
4683         }
4684         void opAssign(S2 other)
4685         {
4686             ni = other.ni;
4687         }
4688     }
4689     static foreach (S; AliasSeq!(S1, S2))
4690     {{
4691         S a;
4692         S b = a;
4693         S c;
4694         c = a;
4695     }}
4696 }
4697 @system unittest
4698 {
4699     import std.conv : to;
4700 
4701     // https://issues.dlang.org/show_bug.cgi?id=10915
4702     Nullable!(int, 1) ni = 1;
4703     assert(ni.to!string() == "Nullable.null");
4704 
4705     struct Test { string s; }
4706     alias NullableTest = Nullable!(Test, Test("null"));
4707 
4708     NullableTest nt = Test("test");
4709     assert(nt.to!string() == `Test("test")`);
4710 
4711     NullableTest ntn = Test("null");
4712     assert(ntn.to!string() == "Nullable.null");
4713 
4714     class TestToString
4715     {
4716         double d;
4717 
4718         this(double d)
4719         {
4720             this.d = d;
4721         }
4722 
4723         override string toString()
4724         {
4725             return d.to!string();
4726         }
4727     }
4728     alias NullableTestToString = Nullable!(TestToString, null);
4729 
4730     NullableTestToString ntts = new TestToString(2.5);
4731     assert(ntts.to!string() == "2.5");
4732 }
4733 
4734 // apply
4735 /**
4736 Unpacks the content of a `Nullable`, performs an operation and packs it again. Does nothing if isNull.
4737 
4738 When called on a `Nullable`, `apply` will unpack the value contained in the `Nullable`,
4739 pass it to the function you provide and wrap the result in another `Nullable` (if necessary).
4740 If the `Nullable` is null, `apply` will return null itself.
4741 
4742 Params:
4743     t = a `Nullable`
4744     fun = a function operating on the content of the nullable
4745 
4746 Returns:
4747     `fun(t.get).nullable` if `!t.isNull`, else `Nullable.init`.
4748 
4749 See also:
4750     $(HTTPS en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad, The `Maybe` monad)
4751 */
4752 template apply(alias fun)
4753 {
4754     import std.functional : unaryFun;
4755 
4756     auto apply(T)(auto ref T t)
4757     if (isInstanceOf!(Nullable, T))
4758     {
4759         alias FunType = typeof(unaryFun!fun(T.init.get));
4760 
4761         enum MustWrapReturn = !isInstanceOf!(Nullable, FunType);
4762 
4763         static if (MustWrapReturn)
4764         {
4765             alias ReturnType = Nullable!FunType;
4766         }
4767         else
4768         {
4769             alias ReturnType = FunType;
4770         }
4771 
4772         if (!t.isNull)
4773         {
4774             static if (MustWrapReturn)
4775             {
4776                 return unaryFun!fun(t.get).nullable;
4777             }
4778             else
4779             {
4780                 return unaryFun!fun(t.get);
4781             }
4782         }
4783         else
4784         {
4785             return ReturnType.init;
4786         }
4787     }
4788 }
4789 
4790 ///
4791 nothrow pure @nogc @safe unittest
4792 {
4793     alias toFloat = i => cast(float) i;
4794 
4795     Nullable!int sample;
4796 
4797     // apply(null) results in a null `Nullable` of the function's return type.
4798     Nullable!float f = sample.apply!toFloat;
4799     assert(sample.isNull && f.isNull);
4800 
4801     sample = 3;
4802 
4803     // apply(non-null) calls the function and wraps the result in a `Nullable`.
4804     f = sample.apply!toFloat;
4805     assert(!sample.isNull && !f.isNull);
4806     assert(f.get == 3.0f);
4807 }
4808 
4809 ///
4810 nothrow pure @nogc @safe unittest
4811 {
4812     alias greaterThree = i => (i > 3) ? i.nullable : Nullable!(typeof(i)).init;
4813 
4814     Nullable!int sample;
4815 
4816     // when the function already returns a `Nullable`, that `Nullable` is not wrapped.
4817     auto result = sample.apply!greaterThree;
4818     assert(sample.isNull && result.isNull);
4819 
4820     // The function may decide to return a null `Nullable`.
4821     sample = 3;
4822     result = sample.apply!greaterThree;
4823     assert(!sample.isNull && result.isNull);
4824 
4825     // Or it may return a value already wrapped in a `Nullable`.
4826     sample = 4;
4827     result = sample.apply!greaterThree;
4828     assert(!sample.isNull && !result.isNull);
4829     assert(result.get == 4);
4830 }
4831 
4832 // test that Nullable.get(default) can merge types
4833 @safe @nogc nothrow pure
4834 unittest
4835 {
4836     Nullable!ubyte sample = Nullable!ubyte();
4837 
4838     // Test that get(U) returns the common type of the Nullable type and the parameter type.
4839     assert(sample.get(1000) == 1000);
4840 }
4841 
4842 // Workaround for https://issues.dlang.org/show_bug.cgi?id=20670
4843 @safe @nogc nothrow pure
4844 unittest
4845 {
4846     immutable struct S { }
4847 
4848     S[] array = Nullable!(S[])().get(S[].init);
4849 }
4850 
4851 // regression test for https://issues.dlang.org/show_bug.cgi?id=21199
4852 @safe @nogc nothrow pure
4853 unittest
4854 {
4855     struct S { int i; }
4856     assert(S(5).nullable.apply!"a.i" == 5);
4857 }
4858 
4859 // regression test for https://issues.dlang.org/show_bug.cgi?id=22176
4860 @safe @nogc nothrow pure
4861 unittest
4862 {
4863     struct S
4864     {
4865         int i;
4866         invariant(i != 0);
4867 
4868         // Nullable shouldn't cause S to generate an
4869         // opAssign that would check the invariant.
4870         Nullable!int j;
4871     }
4872     S s;
4873     s = S(5);
4874 }
4875 
4876 /**
4877 Just like `Nullable!T`, except that the object refers to a value
4878 sitting elsewhere in memory. This makes assignments overwrite the
4879 initially assigned value. Internally `NullableRef!T` only stores a
4880 pointer to `T` (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
4881  */
4882 struct NullableRef(T)
4883 {
4884     private T* _value;
4885 
4886 /**
4887 Constructor binding `this` to `value`.
4888 
4889 Params:
4890     value = The value to bind to.
4891  */
4892     this(T* value) @safe pure nothrow
4893     {
4894         _value = value;
4895     }
4896 
4897     template toString()
4898     {
4899         import std.format.spec : FormatSpec;
4900         import std.format.write : formatValue;
4901         // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4902         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4903         {
4904             if (isNull)
4905             {
4906                 sink.formatValue("Nullable.null", fmt);
4907             }
4908             else
4909             {
4910                 sink.formatValue(*_value, fmt);
4911             }
4912         }
4913 
4914         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4915         {
4916             if (isNull)
4917             {
4918                 sink.formatValue("Nullable.null", fmt);
4919             }
4920             else
4921             {
4922                 sink.formatValue(*_value, fmt);
4923             }
4924         }
4925     }
4926 
4927 @system unittest
4928 {
4929     import std.conv : to;
4930 
4931     const NullableRef!(ulong) x = new ulong(1);
4932     assert(x.to!string == "1");
4933 }
4934 
4935 /**
4936 Binds the internal state to `value`.
4937 
4938 Params:
4939     value = A pointer to a value of type `T` to bind this `NullableRef` to.
4940  */
4941     void bind(T* value) @safe pure nothrow
4942     {
4943         _value = value;
4944     }
4945 
4946     ///
4947     @safe unittest
4948     {
4949         NullableRef!int nr = new int(42);
4950         assert(nr == 42);
4951 
4952         int* n = new int(1);
4953         nr.bind(n);
4954         assert(nr == 1);
4955     }
4956 
4957 /**
4958 Returns `true` if and only if `this` is in the null state.
4959 
4960 Returns:
4961     true if `this` is in the null state, otherwise false.
4962  */
4963     @property bool isNull() const @safe pure nothrow
4964     {
4965         return _value is null;
4966     }
4967 
4968     ///
4969     @safe unittest
4970     {
4971         NullableRef!int nr;
4972         assert(nr.isNull);
4973 
4974         int* n = new int(42);
4975         nr.bind(n);
4976         assert(!nr.isNull && nr == 42);
4977     }
4978 
4979 /**
4980 Forces `this` to the null state.
4981  */
4982     void nullify() @safe pure nothrow
4983     {
4984         _value = null;
4985     }
4986 
4987     ///
4988     @safe unittest
4989     {
4990         NullableRef!int nr = new int(42);
4991         assert(!nr.isNull);
4992 
4993         nr.nullify();
4994         assert(nr.isNull);
4995     }
4996 
4997 /**
4998 Assigns `value` to the internally-held state.
4999 
5000 Params:
5001     value = A value of type `T` to assign to this `NullableRef`.
5002             If the internal state of this `NullableRef` has not
5003             been initialized, an error will be thrown in
5004             non-release mode.
5005  */
5006     void opAssign()(T value)
5007         if (isAssignable!T) //@@@9416@@@
5008     {
5009         enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
5010         assert(!isNull, message);
5011         *_value = value;
5012     }
5013 
5014     ///
5015     @system unittest
5016     {
5017         import std.exception : assertThrown, assertNotThrown;
5018 
5019         NullableRef!int nr;
5020         assert(nr.isNull);
5021         assertThrown!Throwable(nr = 42);
5022 
5023         nr.bind(new int(0));
5024         assert(!nr.isNull);
5025         assertNotThrown!Throwable(nr = 42);
5026         assert(nr == 42);
5027     }
5028 
5029 /**
5030 Gets the value. `this` must not be in the null state.
5031 This function is also called for the implicit conversion to `T`.
5032  */
5033     @property ref inout(T) get() inout @safe pure nothrow
5034     {
5035         enum message = "Called `get' on null NullableRef!" ~ T.stringof ~ ".";
5036         assert(!isNull, message);
5037         return *_value;
5038     }
5039 
5040     ///
5041     @system unittest
5042     {
5043         import std.exception : assertThrown, assertNotThrown;
5044 
5045         NullableRef!int nr;
5046         //`get` is implicitly called. Will throw
5047         //an error in non-release mode
5048         assertThrown!Throwable(nr == 0);
5049 
5050         nr.bind(new int(0));
5051         assertNotThrown!Throwable(nr == 0);
5052     }
5053 
5054 /**
5055 Implicitly converts to `T`.
5056 `this` must not be in the null state.
5057  */
5058     alias get this;
5059 }
5060 
5061 /// ditto
5062 auto nullableRef(T)(T* t)
5063 {
5064     return NullableRef!T(t);
5065 }
5066 
5067 ///
5068 @system unittest
5069 {
5070     import std.exception : assertThrown;
5071 
5072     int x = 5, y = 7;
5073     auto a = nullableRef(&x);
5074     assert(!a.isNull);
5075     assert(a == 5);
5076     assert(x == 5);
5077     a = 42;
5078     assert(x == 42);
5079     assert(!a.isNull);
5080     assert(a == 42);
5081     a.nullify();
5082     assert(x == 42);
5083     assert(a.isNull);
5084     assertThrown!Throwable(a.get);
5085     assertThrown!Throwable(a = 71);
5086     a.bind(&y);
5087     assert(a == 7);
5088     y = 135;
5089     assert(a == 135);
5090 }
5091 @system unittest
5092 {
5093     static int f(scope const NullableRef!int x) {
5094         return x.isNull ? 42 : x.get;
5095     }
5096     int x = 5;
5097     auto a = nullableRef(&x);
5098     assert(f(a) == 5);
5099     a.nullify();
5100     assert(f(a) == 42);
5101 }
5102 @safe unittest
5103 {
5104     // Ensure NullableRef can be used in pure/nothrow/@safe environment.
5105     function() @safe pure nothrow
5106     {
5107         auto storage = new int;
5108         *storage = 19902;
5109         NullableRef!int n;
5110         assert(n.isNull);
5111         n.bind(storage);
5112         assert(!n.isNull);
5113         assert(n == 19902);
5114         n = 2294;
5115         assert(n == 2294);
5116         assert(*storage == 2294);
5117         n.nullify();
5118         assert(n.isNull);
5119     }();
5120 }
5121 @system unittest
5122 {
5123     // Ensure NullableRef can be used when the value is not pure/nothrow/@safe
5124     static struct S
5125     {
5126         int x;
5127         this(this) @system {}
5128         bool opEquals(const S s) const @system { return s.x == x; }
5129     }
5130 
5131     auto storage = S(5);
5132 
5133     NullableRef!S s;
5134     assert(s.isNull);
5135     s.bind(&storage);
5136     assert(!s.isNull);
5137     assert(s.x == 5);
5138     s.nullify();
5139     assert(s.isNull);
5140 }
5141 @safe unittest
5142 {
5143     //Check nullable is nicelly embedable in a struct
5144     static struct S1
5145     {
5146         NullableRef!int ni;
5147     }
5148     static struct S2 //inspired from 9404
5149     {
5150         NullableRef!int ni;
5151         this(S2 other)
5152         {
5153             ni = other.ni;
5154         }
5155         void opAssign(S2 other)
5156         {
5157             ni = other.ni;
5158         }
5159     }
5160     static foreach (S; AliasSeq!(S1, S2))
5161     {{
5162         S a;
5163         S b = a;
5164         S c;
5165         c = a;
5166     }}
5167 }
5168 
5169 // https://issues.dlang.org/show_bug.cgi?id=10915
5170 @system unittest
5171 {
5172     import std.conv : to;
5173 
5174     NullableRef!int nri;
5175     assert(nri.to!string() == "Nullable.null");
5176 
5177     struct Test
5178     {
5179         string s;
5180     }
5181     NullableRef!Test nt = new Test("test");
5182     assert(nt.to!string() == `Test("test")`);
5183 
5184     class TestToString
5185     {
5186         double d;
5187 
5188         this(double d)
5189         {
5190             this.d = d;
5191         }
5192 
5193         override string toString()
5194         {
5195             return d.to!string();
5196         }
5197     }
5198     TestToString tts = new TestToString(2.5);
5199     NullableRef!TestToString ntts = &tts;
5200     assert(ntts.to!string() == "2.5");
5201 }
5202 
5203 
5204 /**
5205 `BlackHole!Base` is a subclass of `Base` which automatically implements
5206 all abstract member functions in `Base` as do-nothing functions.  Each
5207 auto-implemented function just returns the default value of the return type
5208 without doing anything.
5209 
5210 The name came from
5211 $(HTTP search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
5212 Perl module by Sean M. Burke.
5213 
5214 Params:
5215     Base = A non-final class for `BlackHole` to inherit from.
5216 
5217 See_Also:
5218   $(LREF AutoImplement), $(LREF generateEmptyFunction)
5219  */
5220 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction, isAbstractFunction);
5221 
5222 ///
5223 @system unittest
5224 {
5225     import std.math.traits : isNaN;
5226 
5227     static abstract class C
5228     {
5229         int m_value;
5230         this(int v) { m_value = v; }
5231         int value() @property { return m_value; }
5232 
5233         abstract real realValue() @property;
5234         abstract void doSomething();
5235     }
5236 
5237     auto c = new BlackHole!C(42);
5238     assert(c.value == 42);
5239 
5240     // Returns real.init which is NaN
5241     assert(c.realValue.isNaN);
5242     // Abstract functions are implemented as do-nothing
5243     c.doSomething();
5244 }
5245 
5246 @system unittest
5247 {
5248     import std.math.traits : isNaN;
5249 
5250     // return default
5251     {
5252         interface I_1 { real test(); }
5253         auto o = new BlackHole!I_1;
5254         assert(o.test().isNaN()); // NaN
5255     }
5256     // doc example
5257     {
5258         static class C
5259         {
5260             int m_value;
5261             this(int v) { m_value = v; }
5262             int value() @property { return m_value; }
5263 
5264             abstract real realValue() @property;
5265             abstract void doSomething();
5266         }
5267 
5268         auto c = new BlackHole!C(42);
5269         assert(c.value == 42);
5270 
5271         assert(c.realValue.isNaN); // NaN
5272         c.doSomething();
5273     }
5274 
5275     // https://issues.dlang.org/show_bug.cgi?id=12058
5276     interface Foo
5277     {
5278         inout(Object) foo() inout;
5279     }
5280     BlackHole!Foo o;
5281 }
5282 
5283 nothrow pure @nogc @safe unittest
5284 {
5285     static interface I
5286     {
5287         I foo() nothrow pure @nogc @safe return scope;
5288     }
5289 
5290     scope cb = new BlackHole!I();
5291     cb.foo();
5292 }
5293 
5294 
5295 /**
5296 `WhiteHole!Base` is a subclass of `Base` which automatically implements
5297 all abstract member functions as functions that always fail. These functions
5298 simply throw an `Error` and never return. `Whitehole` is useful for
5299 trapping the use of class member functions that haven't been implemented.
5300 
5301 The name came from
5302 $(HTTP search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
5303 Perl module by Michael G Schwern.
5304 
5305 Params:
5306     Base = A non-final class for `WhiteHole` to inherit from.
5307 
5308 See_Also:
5309   $(LREF AutoImplement), $(LREF generateAssertTrap)
5310  */
5311 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap, isAbstractFunction);
5312 
5313 ///
5314 @system unittest
5315 {
5316     import std.exception : assertThrown;
5317 
5318     static class C
5319     {
5320         abstract void notYetImplemented();
5321     }
5322 
5323     auto c = new WhiteHole!C;
5324     assertThrown!NotImplementedError(c.notYetImplemented()); // throws an Error
5325 }
5326 
5327 // https://issues.dlang.org/show_bug.cgi?id=20232
5328 nothrow pure @safe unittest
5329 {
5330     static interface I
5331     {
5332         I foo() nothrow pure @safe return scope;
5333     }
5334 
5335     if (0) // Just checking attribute interference
5336     {
5337         scope cw = new WhiteHole!I();
5338         cw.foo();
5339     }
5340 }
5341 
5342 // / ditto
5343 class NotImplementedError : Error
5344 {
5345     this(string method) nothrow pure @safe
5346     {
5347         super(method ~ " is not implemented");
5348     }
5349 }
5350 
5351 @system unittest
5352 {
5353     import std.exception : assertThrown;
5354     // nothrow
5355     {
5356         interface I_1
5357         {
5358             void foo();
5359             void bar() nothrow;
5360         }
5361         auto o = new WhiteHole!I_1;
5362         assertThrown!NotImplementedError(o.foo());
5363         assertThrown!NotImplementedError(o.bar());
5364     }
5365     // doc example
5366     {
5367         static class C
5368         {
5369             abstract void notYetImplemented();
5370         }
5371 
5372         auto c = new WhiteHole!C;
5373         try
5374         {
5375             c.notYetImplemented();
5376             assert(0);
5377         }
5378         catch (Error e) {}
5379     }
5380 }
5381 
5382 
5383 /**
5384 `AutoImplement` automatically implements (by default) all abstract member
5385 functions in the class or interface `Base` in specified way.
5386 
5387 The second version of `AutoImplement` automatically implements
5388 `Interface`, while deriving from `BaseClass`.
5389 
5390 Params:
5391   how  = template which specifies _how functions will be implemented/overridden.
5392 
5393          Two arguments are passed to `how`: the type `Base` and an alias
5394          to an implemented function.  Then `how` must return an implemented
5395          function body as a string.
5396 
5397          The generated function body can use these keywords:
5398          $(UL
5399             $(LI `a0`, `a1`, &hellip;: arguments passed to the function;)
5400             $(LI `args`: a tuple of the arguments;)
5401             $(LI `self`: an alias to the function itself;)
5402             $(LI `parent`: an alias to the overridden function (if any).)
5403          )
5404 
5405         You may want to use templated property functions (instead of Implicit
5406         Template Properties) to generate complex functions:
5407 --------------------
5408 // Prints log messages for each call to overridden functions.
5409 string generateLogger(C, alias fun)() @property
5410 {
5411     import std.traits;
5412     enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
5413     string stmt;
5414 
5415     stmt ~= q{ struct Importer { import std.stdio; } };
5416     stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
5417     static if (!__traits(isAbstractFunction, fun))
5418     {
5419         static if (is(ReturnType!fun == void))
5420             stmt ~= q{ parent(args); };
5421         else
5422             stmt ~= q{
5423                 auto r = parent(args);
5424                 Importer.writeln("--> ", r);
5425                 return r;
5426             };
5427     }
5428     return stmt;
5429 }
5430 --------------------
5431 
5432   what = template which determines _what functions should be
5433          implemented/overridden.
5434 
5435          An argument is passed to `what`: an alias to a non-final member
5436          function in `Base`.  Then `what` must return a boolean value.
5437          Return `true` to indicate that the passed function should be
5438          implemented/overridden.
5439 
5440 --------------------
5441 // Sees if fun returns something.
5442 enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void);
5443 --------------------
5444 
5445 
5446 Note:
5447 
5448 Generated code is inserted in the scope of `std.typecons` module.  Thus,
5449 any useful functions outside `std.typecons` cannot be used in the generated
5450 code.  To workaround this problem, you may `import` necessary things in a
5451 local struct, as done in the `generateLogger()` template in the above
5452 example.
5453 
5454 
5455 BUGS:
5456 
5457 $(UL
5458  $(LI Variadic arguments to constructors are not forwarded to super.)
5459  $(LI Deep interface inheritance causes compile error with messages like
5460       "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
5461       does not override any function".  [$(BUGZILLA 2525)] )
5462  $(LI The `parent` keyword is actually a delegate to the super class'
5463       corresponding member function.  [$(BUGZILLA 2540)] )
5464  $(LI Using alias template parameter in `how` and/or `what` may cause
5465      strange compile error.  Use template tuple parameter instead to workaround
5466      this problem.  [$(BUGZILLA 4217)] )
5467 )
5468  */
5469 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
5470 if (!is(how == class))
5471 {
5472     private alias autoImplement_helper_ =
5473         AutoImplement_Helper!("autoImplement_helper_", "Base", Base, typeof(this), how, what);
5474     mixin(autoImplement_helper_.code);
5475 }
5476 
5477 /// ditto
5478 class AutoImplement(
5479     Interface, BaseClass, alias how,
5480     alias what = isAbstractFunction) : BaseClass, Interface
5481 if (is(Interface == interface) && is(BaseClass == class))
5482 {
5483     private alias autoImplement_helper_ = AutoImplement_Helper!(
5484             "autoImplement_helper_", "Interface", Interface, typeof(this), how, what);
5485     mixin(autoImplement_helper_.code);
5486 }
5487 
5488 ///
5489 @system unittest
5490 {
5491     interface PackageSupplier
5492     {
5493         int foo();
5494         int bar();
5495     }
5496 
5497     static abstract class AbstractFallbackPackageSupplier : PackageSupplier
5498     {
5499         protected PackageSupplier default_, fallback;
5500 
5501         this(PackageSupplier default_, PackageSupplier fallback)
5502         {
5503             this.default_ = default_;
5504             this.fallback = fallback;
5505         }
5506 
5507         abstract int foo();
5508         abstract int bar();
5509     }
5510 
5511     template fallback(T, alias func)
5512     {
5513         import std.format : format;
5514         // for all implemented methods:
5515         // - try default first
5516         // - only on a failure run & return fallback
5517         enum fallback = q{
5518             try
5519             {
5520                 return default_.%1$s(args);
5521             }
5522             catch (Exception)
5523             {
5524                 return fallback.%1$s(args);
5525             }
5526         }.format(__traits(identifier, func));
5527     }
5528 
5529     // combines two classes and use the second one as fallback
5530     alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback);
5531 
5532     class FailingPackageSupplier : PackageSupplier
5533     {
5534         int foo(){ throw new Exception("failure"); }
5535         int bar(){ return 2;}
5536     }
5537 
5538     class BackupPackageSupplier : PackageSupplier
5539     {
5540         int foo(){ return -1; }
5541         int bar(){ return -1;}
5542     }
5543 
5544     auto registry = new FallbackPackageSupplier(new FailingPackageSupplier(), new BackupPackageSupplier());
5545 
5546     assert(registry.foo() == -1);
5547     assert(registry.bar() == 2);
5548 }
5549 
5550 /*
5551  * Code-generating stuffs are encupsulated in this helper template so that
5552  * namespace pollution, which can cause name confliction with Base's public
5553  * members, should be minimized.
5554  */
5555 private template AutoImplement_Helper(string myName, string baseName,
5556         Base, Self, alias generateMethodBody, alias cherrypickMethod)
5557 {
5558 private static:
5559     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5560     // Internal stuffs
5561     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5562 
5563     // Returns function overload sets in the class C, filtered with pred.
5564     template enumerateOverloads(C, alias pred)
5565     {
5566         template Impl(names...)
5567         {
5568             import std.meta : Filter;
5569             static if (names.length > 0)
5570             {
5571                 alias methods = Filter!(pred, MemberFunctionsTuple!(C, names[0]));
5572                 alias next = Impl!(names[1 .. $]);
5573 
5574                 static if (methods.length > 0)
5575                     alias Impl = AliasSeq!(OverloadSet!(names[0], methods), next);
5576                 else
5577                     alias Impl = next;
5578             }
5579             else
5580                 alias Impl = AliasSeq!();
5581         }
5582 
5583         alias enumerateOverloads = Impl!(__traits(allMembers, C));
5584     }
5585 
5586     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5587     // Target functions
5588     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5589 
5590     // Add a non-final check to the cherrypickMethod.
5591     enum bool canonicalPicker(fun.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/) =
5592         !__traits(isFinalFunction, fun[0]) && cherrypickMethod!(fun);
5593 
5594     /*
5595      * A tuple of overload sets, each item of which consists of functions to be
5596      * implemented by the generated code.
5597      */
5598     alias targetOverloadSets = enumerateOverloads!(Base, canonicalPicker);
5599 
5600     /*
5601      * Super class of this AutoImplement instance
5602      */
5603     alias Super = BaseTypeTuple!(Self)[0];
5604     static assert(is(Super == class));
5605     static assert(is(Base == interface) || is(Super == Base));
5606 
5607     /*
5608      * A tuple of the super class' constructors.  Used for forwarding
5609      * constructor calls.
5610      */
5611     static if (__traits(hasMember, Super, "__ctor"))
5612         alias ctorOverloadSet = OverloadSet!("__ctor", __traits(getOverloads, Super, "__ctor"));
5613     else
5614         alias ctorOverloadSet = OverloadSet!("__ctor"); // empty
5615 
5616 
5617     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5618     // Type information
5619     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5620 
5621     /*
5622      * The generated code will be mixed into AutoImplement, which will be
5623      * instantiated in this module's scope.  Thus, any user-defined types are
5624      * out of scope and cannot be used directly (i.e. by their names).
5625      *
5626      * We will use FuncInfo instances for accessing return types and parameter
5627      * types of the implemented functions.  The instances will be populated to
5628      * the AutoImplement's scope in a certain way; see the populate() below.
5629      */
5630 
5631     // Returns the preferred identifier for the FuncInfo instance for the i-th
5632     // overloaded function with the name.
5633     template INTERNAL_FUNCINFO_ID(string name, size_t i)
5634     {
5635         import std.format : format;
5636 
5637         enum string INTERNAL_FUNCINFO_ID = format("F_%s_%s", name, i);
5638     }
5639 
5640     /*
5641      * Insert FuncInfo instances about all the target functions here.  This
5642      * enables the generated code to access type information via, for example,
5643      * "autoImplement_helper_.F_foo_1".
5644      */
5645     template populate(overloads...)
5646     {
5647         static if (overloads.length > 0)
5648         {
5649             mixin populate!(overloads[0].name, overloads[0].contents);
5650             mixin populate!(overloads[1 .. $]);
5651         }
5652     }
5653     template populate(string name, methods...)
5654     {
5655         static if (methods.length > 0)
5656         {
5657             mixin populate!(name, methods[0 .. $ - 1]);
5658             //
5659             alias target = methods[$ - 1];
5660             enum ith = methods.length - 1;
5661             mixin("alias " ~ INTERNAL_FUNCINFO_ID!(name, ith) ~ " = FuncInfo!target;");
5662         }
5663     }
5664 
5665     public mixin populate!(targetOverloadSets);
5666     public mixin populate!(  ctorOverloadSet );
5667 
5668 
5669     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5670     // Code-generating policies
5671     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5672 
5673     /* Common policy configurations for generating constructors and methods. */
5674     template CommonGeneratingPolicy()
5675     {
5676         // base class identifier which generated code should use
5677         enum string BASE_CLASS_ID = baseName;
5678 
5679         // FuncInfo instance identifier which generated code should use
5680         template FUNCINFO_ID(string name, size_t i)
5681         {
5682             enum string FUNCINFO_ID =
5683                 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
5684         }
5685     }
5686 
5687     /* Policy configurations for generating constructors. */
5688     template ConstructorGeneratingPolicy()
5689     {
5690         mixin CommonGeneratingPolicy;
5691 
5692         /* Generates constructor body.  Just forward to the base class' one. */
5693         string generateFunctionBody(ctor.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5694         {
5695             enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
5696 
5697             static if (varstyle & (Variadic.c | Variadic.d))
5698             {
5699                 // the argptr-forwarding problem
5700                 //pragma(msg, "Warning: AutoImplement!(", Base, ") ",
5701                 //        "ignored variadic arguments to the constructor ",
5702                 //        FunctionTypeOf!(typeof(&ctor[0])) );
5703             }
5704             return "super(args);";
5705         }
5706     }
5707 
5708     /* Policy configurations for genearting target methods. */
5709     template MethodGeneratingPolicy()
5710     {
5711         mixin CommonGeneratingPolicy;
5712 
5713         /* Geneartes method body. */
5714         string generateFunctionBody(func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5715         {
5716             return generateMethodBody!(Base, func); // given
5717         }
5718     }
5719 
5720 
5721     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5722     // Generated code
5723     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5724 
5725     alias ConstructorGenerator = MemberFunctionGenerator!(ConstructorGeneratingPolicy!());
5726     alias MethodGenerator      = MemberFunctionGenerator!(MethodGeneratingPolicy!());
5727 
5728     public enum string code =
5729         ConstructorGenerator.generateCode!(  ctorOverloadSet ) ~ "\n" ~
5730              MethodGenerator.generateCode!(targetOverloadSets);
5731 
5732     debug (SHOW_GENERATED_CODE)
5733     {
5734         pragma(msg, "-------------------- < ", Base, " >");
5735         pragma(msg, code);
5736         pragma(msg, "--------------------");
5737     }
5738 }
5739 
5740 //debug = SHOW_GENERATED_CODE;
5741 @system unittest
5742 {
5743     import core.vararg;
5744     // no function to implement
5745     {
5746         interface I_1 {}
5747         auto o = new BlackHole!I_1;
5748     }
5749     // parameters
5750     {
5751         interface I_3 { void test(int, in int, out int, ref int, lazy int); }
5752         auto o = new BlackHole!I_3;
5753     }
5754     // use of user-defined type
5755     {
5756         struct S {}
5757         interface I_4 { S test(); }
5758         auto o = new BlackHole!I_4;
5759     }
5760     // overloads
5761     {
5762         interface I_5
5763         {
5764             void test(string);
5765             real test(real);
5766             int  test();
5767         }
5768         auto o = new BlackHole!I_5;
5769     }
5770     // constructor forwarding
5771     {
5772         static class C_6
5773         {
5774             this(int n) { assert(n == 42); }
5775             this(string s) { assert(s == "Deeee"); }
5776             this(...) {}
5777         }
5778         auto o1 = new BlackHole!C_6(42);
5779         auto o2 = new BlackHole!C_6("Deeee");
5780         auto o3 = new BlackHole!C_6(1, 2, 3, 4);
5781     }
5782     // attributes
5783     {
5784         interface I_7
5785         {
5786             ref int test_ref();
5787             int test_pure() pure;
5788             int test_nothrow() nothrow;
5789             int test_property() @property;
5790             int test_safe() @safe;
5791             int test_trusted() @trusted;
5792             int test_system() @system;
5793             int test_pure_nothrow() pure nothrow;
5794         }
5795         auto o = new BlackHole!I_7;
5796     }
5797     // storage classes
5798     {
5799         interface I_8
5800         {
5801             void test_const() const;
5802             void test_immutable() immutable;
5803             void test_shared() shared;
5804             void test_shared_const() shared const;
5805         }
5806         auto o = new BlackHole!I_8;
5807     }
5808     // use baseclass
5809     {
5810         static class C_9
5811         {
5812             private string foo_;
5813 
5814             this(string s) {
5815                 foo_ = s;
5816             }
5817 
5818             protected string boilerplate() @property
5819             {
5820                 return "Boilerplate stuff.";
5821             }
5822 
5823             public string foo() @property
5824             {
5825                 return foo_;
5826             }
5827         }
5828 
5829         interface I_10
5830         {
5831             string testMethod(size_t);
5832         }
5833 
5834         static string generateTestMethod(C, alias fun)() @property
5835         {
5836             return "return this.boilerplate[0 .. a0];";
5837         }
5838 
5839         auto o = new AutoImplement!(I_10, C_9, generateTestMethod)("Testing");
5840         assert(o.testMethod(11) == "Boilerplate");
5841         assert(o.foo == "Testing");
5842     }
5843     /+ // deep inheritance
5844     {
5845     // https://issues.dlang.org/show_bug.cgi?id=2525
5846     // https://issues.dlang.org/show_bug.cgi?id=3525
5847     // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
5848         interface I { void foo(); }
5849         interface J : I {}
5850         interface K : J {}
5851         static abstract class C_9 : K {}
5852         auto o = new BlackHole!C_9;
5853     }+/
5854     // test `parent` alias
5855     {
5856         interface I_11
5857         {
5858             void simple(int) @safe;
5859             int anotherSimple(string);
5860             int overloaded(int);
5861             /+ XXX [BUG 19715]
5862             void overloaded(string) @safe;
5863             +/
5864         }
5865 
5866         static class C_11
5867         {
5868             import std.traits : Parameters, ReturnType;
5869             import std.meta : Alias;
5870 
5871             protected ReturnType!fn _impl(alias fn)(Parameters!fn)
5872             if (is(Alias!(__traits(parent, fn)) == interface))
5873             {
5874                 static if (!is(typeof(return) == void))
5875                     return typeof(return).init;
5876             }
5877         }
5878 
5879         template tpl(I, alias fn)
5880         if (is(I == interface) && __traits(isSame, __traits(parent, fn), I))
5881         {
5882             enum string tpl = q{
5883                 enum bool haveReturn = !is(typeof(return) == void);
5884 
5885                 static if (is(typeof(return) == void))
5886                     _impl!parent(args);
5887                 else
5888                     return _impl!parent(args);
5889             };
5890         }
5891 
5892         auto o = new AutoImplement!(I_11, C_11, tpl);
5893     }
5894 }
5895 
5896 // https://issues.dlang.org/show_bug.cgi?id=17177
5897 // AutoImplement fails on function overload sets with
5898 // "cannot infer type from overloaded function symbol"
5899 @system unittest
5900 {
5901     static class Issue17177
5902     {
5903         private string n_;
5904 
5905         public {
5906             Issue17177 overloaded(string n)
5907             {
5908                 this.n_ = n;
5909 
5910                 return this;
5911             }
5912 
5913             string overloaded()
5914             {
5915                 return this.n_;
5916             }
5917         }
5918     }
5919 
5920     static string how(C, alias fun)()
5921     {
5922         static if (!is(ReturnType!fun == void))
5923         {
5924             return q{
5925                 return parent(args);
5926             };
5927         }
5928         else
5929         {
5930             return q{
5931                 parent(args);
5932             };
5933         }
5934     }
5935 
5936     import std.meta : templateNot;
5937     alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction);
5938 }
5939 
5940 version (StdUnittest)
5941 {
5942     // https://issues.dlang.org/show_bug.cgi?id=10647
5943     // Add prefix "issue10647_" as a workaround for
5944     // https://issues.dlang.org/show_bug.cgi?id=1238
5945     private string issue10647_generateDoNothing(C, alias fun)() @property
5946     {
5947         string stmt;
5948 
5949         static if (is(ReturnType!fun == void))
5950             stmt ~= "";
5951         else
5952         {
5953             string returnType = ReturnType!fun.stringof;
5954             stmt ~= "return "~returnType~".init;";
5955         }
5956         return stmt;
5957     }
5958 
5959     private template issue10647_isAlwaysTrue(alias fun)
5960     {
5961         enum issue10647_isAlwaysTrue = true;
5962     }
5963 
5964     // Do nothing template
5965     private template issue10647_DoNothing(Base)
5966     {
5967         alias issue10647_DoNothing = AutoImplement!(Base, issue10647_generateDoNothing, issue10647_isAlwaysTrue);
5968     }
5969 
5970     // A class to be overridden
5971     private class issue10647_Foo{
5972         void bar(int a) { }
5973     }
5974 }
5975 
5976 @system unittest
5977 {
5978     auto foo = new issue10647_DoNothing!issue10647_Foo();
5979     foo.bar(13);
5980 }
5981 
5982 /*
5983 Used by MemberFunctionGenerator.
5984  */
5985 package template OverloadSet(string nam, T...)
5986 {
5987     enum string name = nam;
5988     alias contents = T;
5989 }
5990 
5991 /*
5992 Used by MemberFunctionGenerator.
5993  */
5994 package template FuncInfo(alias func)
5995 if (is(typeof(&func)))
5996 {
5997     alias RT = ReturnType!(typeof(&func));
5998     alias PT = Parameters!(typeof(&func));
5999 }
6000 package template FuncInfo(Func)
6001 {
6002     alias RT = ReturnType!Func;
6003     alias PT = Parameters!Func;
6004 }
6005 
6006 /*
6007 General-purpose member function generator.
6008 --------------------
6009 template GeneratingPolicy()
6010 {
6011     // [optional] the name of the class where functions are derived
6012     enum string BASE_CLASS_ID;
6013 
6014     // [optional] define this if you have only function types
6015     enum bool WITHOUT_SYMBOL;
6016 
6017     // [optional] Returns preferred identifier for i-th parameter.
6018     template PARAMETER_VARIABLE_ID(size_t i);
6019 
6020     // Returns the identifier of the FuncInfo instance for the i-th overload
6021     // of the specified name.  The identifier must be accessible in the scope
6022     // where generated code is mixed.
6023     template FUNCINFO_ID(string name, size_t i);
6024 
6025     // Returns implemented function body as a string.  When WITHOUT_SYMBOL is
6026     // defined, the latter is used.
6027     template generateFunctionBody(alias func);
6028     template generateFunctionBody(string name, FuncType);
6029 }
6030 --------------------
6031  */
6032 package template MemberFunctionGenerator(alias Policy)
6033 {
6034 private static:
6035     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6036     // Internal stuffs
6037     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6038     import std.format;
6039     alias format = std.format.format;
6040 
6041     enum CONSTRUCTOR_NAME = "__ctor";
6042 
6043     // true if functions are derived from a base class
6044     enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
6045 
6046     // true if functions are specified as types, not symbols
6047     enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
6048 
6049     // preferred identifier for i-th parameter variable
6050     static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
6051     {
6052         alias PARAMETER_VARIABLE_ID = Policy.PARAMETER_VARIABLE_ID;
6053     }
6054     else
6055     {
6056         enum string PARAMETER_VARIABLE_ID(size_t i) = format("a%s", i);
6057             // default: a0, a1, ...
6058     }
6059 
6060     // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach.
6061     template CountUp(size_t n)
6062     {
6063         static if (n > 0)
6064             alias CountUp = AliasSeq!(CountUp!(n - 1), n - 1);
6065         else
6066             alias CountUp = AliasSeq!();
6067     }
6068 
6069 
6070     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6071     // Code generator
6072     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6073 
6074     /*
6075      * Runs through all the target overload sets and generates D code which
6076      * implements all the functions in the overload sets.
6077      */
6078     public string generateCode(overloads...)() @property
6079     {
6080         string code = "";
6081 
6082         // run through all the overload sets
6083         foreach (i_; CountUp!(0 + overloads.length)) // workaround
6084         {
6085             enum i = 0 + i_; // workaround
6086             alias oset = overloads[i];
6087 
6088             code ~= generateCodeForOverloadSet!(oset);
6089 
6090             static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
6091             {
6092                 // The generated function declarations may hide existing ones
6093                 // in the base class (cf. HiddenFuncError), so we put an alias
6094                 // declaration here to reveal possible hidden functions.
6095                 code ~= format("alias %s = %s.%s;\n",
6096                             oset.name,
6097                             // super: https://issues.dlang.org/show_bug.cgi?id=2540
6098                             Policy.BASE_CLASS_ID,
6099                             oset.name);
6100             }
6101         }
6102         return code;
6103     }
6104 
6105     // handle each overload set
6106     string generateCodeForOverloadSet(alias oset)() @property
6107     {
6108         string code = "";
6109 
6110         foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
6111         {
6112             enum i = 0 + i_; // workaround
6113             code ~= generateFunction!(
6114                     Policy.FUNCINFO_ID!(oset.name, i), oset.name,
6115                     oset.contents[i]) ~ "\n";
6116         }
6117         return code;
6118     }
6119 
6120     /*
6121      * Returns D code which implements the function func.  This function
6122      * actually generates only the declarator part; the function body part is
6123      * generated by the functionGenerator() policy.
6124      */
6125     public string generateFunction(
6126             string myFuncInfo, string name, func... )() @property
6127     {
6128         import std.format : format;
6129 
6130         enum isCtor = (name == CONSTRUCTOR_NAME);
6131 
6132         string code; // the result
6133 
6134         auto paramsRes = generateParameters!(myFuncInfo, func)();
6135         code ~= paramsRes.imports;
6136 
6137         /*** Function Declarator ***/
6138         {
6139             alias Func = FunctionTypeOf!(func);
6140             alias FA = FunctionAttribute;
6141             enum atts     = functionAttributes!(func);
6142             enum realName = isCtor ? "this" : name;
6143 
6144             // FIXME?? Make it so that these aren't CTFE funcs any more, since
6145             // Format is deprecated, and format works at compile time?
6146             /* Made them CTFE funcs just for the sake of Format!(...) */
6147 
6148             // return type with optional "ref"
6149             static string make_returnType()
6150             {
6151                 string rtype = "";
6152 
6153                 if (!isCtor)
6154                 {
6155                     if (atts & FA.ref_) rtype ~= "ref ";
6156                     rtype ~= myFuncInfo ~ ".RT";
6157                 }
6158                 return rtype;
6159             }
6160             enum returnType = make_returnType();
6161 
6162             // function attributes attached after declaration
6163             static string make_postAtts()
6164             {
6165                 string poatts = "";
6166                 if (atts & FA.pure_   ) poatts ~= " pure";
6167                 if (atts & FA.nothrow_) poatts ~= " nothrow";
6168                 if (atts & FA.property) poatts ~= " @property";
6169                 if (atts & FA.safe    ) poatts ~= " @safe";
6170                 if (atts & FA.trusted ) poatts ~= " @trusted";
6171                 if (atts & FA.scope_ )  poatts ~= " scope";
6172                 if (atts & FA.return_ ) poatts ~= " return";
6173                 return poatts;
6174             }
6175             enum postAtts = make_postAtts();
6176 
6177             // function storage class
6178             static string make_storageClass()
6179             {
6180                 string postc = "";
6181                 if (is(Func ==    shared)) postc ~= " shared";
6182                 if (is(Func ==     const)) postc ~= " const";
6183                 if (is(Func ==     inout)) postc ~= " inout";
6184                 if (is(Func == immutable)) postc ~= " immutable";
6185                 return postc;
6186             }
6187             enum storageClass = make_storageClass();
6188 
6189             //
6190             if (__traits(isVirtualMethod, func))
6191                 code ~= "override ";
6192             code ~= format("extern(%s) %s %s(%s) %s %s\n",
6193                     functionLinkage!(func),
6194                     returnType,
6195                     realName,
6196                     paramsRes.params,
6197                     postAtts, storageClass );
6198         }
6199 
6200         /*** Function Body ***/
6201         code ~= "{\n";
6202         {
6203             enum nparams = Parameters!(func).length;
6204 
6205             /* Declare keywords: args, self and parent. */
6206             string preamble;
6207 
6208             preamble ~= "alias args = AliasSeq!(" ~ enumerateParameters!(nparams) ~ ");\n";
6209             if (!isCtor)
6210             {
6211                 preamble ~= "alias self = " ~ name ~ ";\n";
6212                 static if (WITH_BASE_CLASS)
6213                     preamble ~= `alias parent = __traits(getMember, ` ~ Policy.BASE_CLASS_ID ~ `, "` ~ name ~ `");`;
6214             }
6215 
6216             // Function body
6217             static if (WITHOUT_SYMBOL)
6218                 enum fbody = Policy.generateFunctionBody!(name, func);
6219             else
6220                 enum fbody = Policy.generateFunctionBody!(func);
6221 
6222             code ~= preamble;
6223             code ~= fbody;
6224         }
6225         code ~= "}";
6226 
6227         return code;
6228     }
6229 
6230     /*
6231      * Returns D code which declares function parameters,
6232      * and optionally any imports (e.g. core.vararg)
6233      * "ref int a0, real a1, ..."
6234      */
6235     static struct GenParams { string imports, params; }
6236     GenParams generateParameters(string myFuncInfo, func...)()
6237     {
6238         alias STC = ParameterStorageClass;
6239         alias stcs = ParameterStorageClassTuple!(func);
6240         enum nparams = stcs.length;
6241 
6242         string imports = ""; // any imports required
6243         string params = ""; // parameters
6244 
6245         foreach (i, stc; stcs)
6246         {
6247             if (i > 0) params ~= ", ";
6248 
6249             // Parameter storage classes.
6250             if (stc & STC.scope_) params ~= "scope ";
6251             if (stc & STC.in_)    params ~= "in ";
6252             if (stc & STC.out_  ) params ~= "out ";
6253             if (stc & STC.ref_  ) params ~= "ref ";
6254             if (stc & STC.lazy_ ) params ~= "lazy ";
6255 
6256             // Take parameter type from the FuncInfo.
6257             params ~= format("%s.PT[%s]", myFuncInfo, i);
6258 
6259             // Declare a parameter variable.
6260             params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
6261         }
6262 
6263         // Add some ellipsis part if needed.
6264         auto style = variadicFunctionStyle!(func);
6265         final switch (style)
6266         {
6267             case Variadic.no:
6268                 break;
6269 
6270             case Variadic.c, Variadic.d:
6271                 imports ~= "import core.vararg;\n";
6272                 // (...) or (a, b, ...)
6273                 params ~= (nparams == 0) ? "..." : ", ...";
6274                 break;
6275 
6276             case Variadic.typesafe:
6277                 params ~= " ...";
6278                 break;
6279         }
6280 
6281         return typeof(return)(imports, params);
6282     }
6283 
6284     // Returns D code which enumerates n parameter variables using comma as the
6285     // separator.  "a0, a1, a2, a3"
6286     string enumerateParameters(size_t n)() @property
6287     {
6288         string params = "";
6289 
6290         foreach (i_; CountUp!(n))
6291         {
6292             enum i = 0 + i_; // workaround
6293             if (i > 0) params ~= ", ";
6294             params ~= PARAMETER_VARIABLE_ID!(i);
6295         }
6296         return params;
6297     }
6298 }
6299 
6300 
6301 /**
6302 Predefined how-policies for `AutoImplement`.  These templates are also used by
6303 `BlackHole` and `WhiteHole`, respectively.
6304  */
6305 template generateEmptyFunction(C, func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)
6306 {
6307     static if (is(ReturnType!(func) == void))
6308         enum string generateEmptyFunction = q{
6309         };
6310     else static if (functionAttributes!(func) & FunctionAttribute.ref_)
6311         enum string generateEmptyFunction = q{
6312             static typeof(return) dummy;
6313             return dummy;
6314         };
6315     else
6316         enum string generateEmptyFunction = q{
6317             return typeof(return).init;
6318         };
6319 }
6320 
6321 ///
6322 @system unittest
6323 {
6324     alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction);
6325 
6326     interface I
6327     {
6328         int foo();
6329         string bar();
6330     }
6331 
6332     auto i = new BlackHole!I();
6333     // generateEmptyFunction returns the default value of the return type without doing anything
6334     assert(i.foo == 0);
6335     assert(i.bar is null);
6336 }
6337 
6338 /// ditto
6339 template generateAssertTrap(C, func...)
6340 {
6341     enum string generateAssertTrap =
6342         `throw new NotImplementedError("` ~ C.stringof ~ "."
6343                 ~ __traits(identifier, func) ~ `");`;
6344 }
6345 
6346 ///
6347 @system unittest
6348 {
6349     import std.exception : assertThrown;
6350 
6351     alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap);
6352 
6353     interface I
6354     {
6355         int foo();
6356         string bar();
6357     }
6358 
6359     auto i = new WhiteHole!I();
6360     // generateAssertTrap throws an exception for every unimplemented function of the interface
6361     assertThrown!NotImplementedError(i.foo);
6362     assertThrown!NotImplementedError(i.bar);
6363 }
6364 
6365 private
6366 {
6367     pragma(mangle, "_d_toObject")
6368     extern(C) pure nothrow Object typecons_d_toObject(void* p);
6369 }
6370 
6371 /*
6372  * Avoids opCast operator overloading.
6373  */
6374 private template dynamicCast(T)
6375 if (is(T == class) || is(T == interface))
6376 {
6377     @trusted
6378     T dynamicCast(S)(inout S source)
6379     if (is(S == class) || is(S == interface))
6380     {
6381         static if (is(Unqual!S : Unqual!T))
6382         {
6383             import std.traits : QualifierOf;
6384             alias Qual = QualifierOf!S; // SharedOf or MutableOf
6385             alias TmpT = Qual!(Unqual!T);
6386             inout(TmpT) tmp = source;   // bypass opCast by implicit conversion
6387             return *cast(T*)(&tmp);     // + variable pointer cast + dereference
6388         }
6389         else
6390         {
6391             return cast(T) typecons_d_toObject(*cast(void**)(&source));
6392         }
6393     }
6394 }
6395 
6396 @system unittest
6397 {
6398     class C { @disable void opCast(T)(); }
6399     auto c = new C;
6400     static assert(!__traits(compiles, cast(Object) c));
6401     auto o = dynamicCast!Object(c);
6402     assert(c is o);
6403 
6404     interface I { @disable void opCast(T)(); Object instance(); }
6405     interface J { @disable void opCast(T)(); Object instance(); }
6406     class D : I, J { Object instance() { return this; } }
6407     I i = new D();
6408     static assert(!__traits(compiles, cast(J) i));
6409     J j = dynamicCast!J(i);
6410     assert(i.instance() is j.instance());
6411 }
6412 
6413 /**
6414 Supports structural based typesafe conversion.
6415 
6416 If `Source` has structural conformance with the `interface` `Targets`,
6417 wrap creates an internal wrapper class which inherits `Targets` and
6418 wraps the `src` object, then returns it.
6419 
6420 `unwrap` can be used to extract objects which have been wrapped by `wrap`.
6421 */
6422 template wrap(Targets...)
6423 if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
6424 {
6425     import std.meta : staticMap;
6426 
6427     // strict upcast
6428     auto wrap(Source)(inout Source src) @trusted pure nothrow
6429     if (Targets.length == 1 && is(Source : Targets[0]))
6430     {
6431         alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]);
6432         return dynamicCast!(inout T)(src);
6433     }
6434     // structural upcast
6435     template wrap(Source)
6436     if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets))
6437     {
6438         auto wrap(inout Source src)
6439         {
6440             static assert(hasRequireMethods!(),
6441                           "Source "~Source.stringof~
6442                           " does not have structural conformance to "~
6443                           Targets.stringof);
6444 
6445             alias T = Select!(is(Source == shared), shared Impl, Impl);
6446             return new inout T(src);
6447         }
6448 
6449         template FuncInfo(string s, F)
6450         {
6451             enum name = s;
6452             alias type = F;
6453         }
6454 
6455         // https://issues.dlang.org/show_bug.cgi?id=12064: Remove NVI members
6456         template OnlyVirtual(members...)
6457         {
6458             enum notFinal(alias T) = !__traits(isFinalFunction, T);
6459             import std.meta : Filter;
6460             alias OnlyVirtual = Filter!(notFinal, members);
6461         }
6462 
6463         // Concat all Targets function members into one tuple
6464         template Concat(size_t i = 0)
6465         {
6466             static if (i >= Targets.length)
6467                 alias Concat = AliasSeq!();
6468             else
6469             {
6470                 alias Concat = AliasSeq!(OnlyVirtual!(GetOverloadedMethods!(Targets[i]), Concat!(i + 1)));
6471             }
6472         }
6473 
6474         // Remove duplicated functions based on the identifier name and function type covariance
6475         template Uniq(members...)
6476         {
6477             static if (members.length == 0)
6478                 alias Uniq = AliasSeq!();
6479             else
6480             {
6481                 alias func = members[0];
6482                 enum  name = __traits(identifier, func);
6483                 alias type = FunctionTypeOf!func;
6484                 template check(size_t i, mem...)
6485                 {
6486                     static if (i >= mem.length)
6487                         enum ptrdiff_t check = -1;
6488                     else
6489                     {
6490                         enum ptrdiff_t check =
6491                             __traits(identifier, func) == __traits(identifier, mem[i]) &&
6492                             !is(DerivedFunctionType!(type, FunctionTypeOf!(mem[i])) == void)
6493                           ? i : check!(i + 1, mem);
6494                     }
6495                 }
6496                 enum ptrdiff_t x = 1 + check!(0, members[1 .. $]);
6497                 static if (x >= 1)
6498                 {
6499                     alias typex = DerivedFunctionType!(type, FunctionTypeOf!(members[x]));
6500                     alias remain = Uniq!(members[1 .. x], members[x + 1 .. $]);
6501 
6502                     static if (remain.length >= 1 && remain[0].name == name &&
6503                                !is(DerivedFunctionType!(typex, remain[0].type) == void))
6504                     {
6505                         alias F = DerivedFunctionType!(typex, remain[0].type);
6506                         alias Uniq = AliasSeq!(FuncInfo!(name, F), remain[1 .. $]);
6507                     }
6508                     else
6509                         alias Uniq = AliasSeq!(FuncInfo!(name, typex), remain);
6510                 }
6511                 else
6512                 {
6513                     alias Uniq = AliasSeq!(FuncInfo!(name, type), Uniq!(members[1 .. $]));
6514                 }
6515             }
6516         }
6517         alias TargetMembers = Uniq!(Concat!());             // list of FuncInfo
6518         alias SourceMembers = GetOverloadedMethods!Source;  // list of function symbols
6519 
6520         // Check whether all of SourceMembers satisfy covariance target in TargetMembers
6521         template hasRequireMethods(size_t i = 0)
6522         {
6523             static if (i >= TargetMembers.length)
6524                 enum hasRequireMethods = true;
6525             else
6526             {
6527                 enum hasRequireMethods =
6528                     findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 &&
6529                     hasRequireMethods!(i + 1);
6530             }
6531         }
6532 
6533         // Internal wrapper class
6534         final class Impl : Structural, Targets
6535         {
6536         private:
6537             Source _wrap_source;
6538 
6539             this(       inout Source s)        inout @safe pure nothrow { _wrap_source = s; }
6540             this(shared inout Source s) shared inout @safe pure nothrow { _wrap_source = s; }
6541 
6542             // BUG: making private should work with NVI.
6543             protected final inout(Object) _wrap_getSource() inout @trusted
6544             {
6545                 return dynamicCast!(inout Object)(_wrap_source);
6546             }
6547 
6548             import std.conv : to;
6549             import core.lifetime : forward;
6550             template generateFun(size_t i)
6551             {
6552                 enum name = TargetMembers[i].name;
6553                 enum fa = functionAttributes!(TargetMembers[i].type);
6554                 static @property stc()
6555                 {
6556                     string r;
6557                     if (fa & FunctionAttribute.property)    r ~= "@property ";
6558                     if (fa & FunctionAttribute.ref_)        r ~= "ref ";
6559                     if (fa & FunctionAttribute.pure_)       r ~= "pure ";
6560                     if (fa & FunctionAttribute.nothrow_)    r ~= "nothrow ";
6561                     if (fa & FunctionAttribute.trusted)     r ~= "@trusted ";
6562                     if (fa & FunctionAttribute.safe)        r ~= "@safe ";
6563                     return r;
6564                 }
6565                 static @property mod()
6566                 {
6567                     alias type = AliasSeq!(TargetMembers[i].type)[0];
6568                     string r;
6569                     static if (is(type == immutable))       r ~= " immutable";
6570                     else
6571                     {
6572                         static if (is(type == shared))      r ~= " shared";
6573                         static if (is(type == const))       r ~= " const";
6574                         else static if (is(type == inout))  r ~= " inout";
6575                         //else  --> mutable
6576                     }
6577                     return r;
6578                 }
6579                 enum n = to!string(i);
6580                 static if (fa & FunctionAttribute.property)
6581                 {
6582                     static if (Parameters!(TargetMembers[i].type).length == 0)
6583                         enum fbody = "_wrap_source."~name;
6584                     else
6585                         enum fbody = "_wrap_source."~name~" = forward!args";
6586                 }
6587                 else
6588                 {
6589                         enum fbody = "_wrap_source."~name~"(forward!args)";
6590                 }
6591                 enum generateFun =
6592                     "override "~stc~"ReturnType!(TargetMembers["~n~"].type) "
6593                     ~ name~"(Parameters!(TargetMembers["~n~"].type) args) "~mod~
6594                     "{ return "~fbody~"; }";
6595             }
6596 
6597         public:
6598             static foreach (i; 0 .. TargetMembers.length)
6599                 mixin(generateFun!i);
6600         }
6601     }
6602 }
6603 /// ditto
6604 template wrap(Targets...)
6605 if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))
6606 {
6607     import std.meta : staticMap;
6608 
6609     alias wrap = .wrap!(staticMap!(Unqual, Targets));
6610 }
6611 
6612 /// ditto
6613 template unwrap(Target)
6614 if (isMutable!Target)
6615 {
6616     // strict downcast
6617     auto unwrap(Source)(inout Source src) @trusted pure nothrow
6618     if (is(Target : Source))
6619     {
6620         alias T = Select!(is(Source == shared), shared Target, Target);
6621         return dynamicCast!(inout T)(src);
6622     }
6623     // structural downcast
6624     auto unwrap(Source)(inout Source src) @trusted pure nothrow
6625     if (!is(Target : Source))
6626     {
6627         alias T = Select!(is(Source == shared), shared Target, Target);
6628         Object o = dynamicCast!(Object)(src);   // remove qualifier
6629         do
6630         {
6631             if (auto a = dynamicCast!(Structural)(o))
6632             {
6633                 if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource()))
6634                     return d;
6635             }
6636             else if (auto d = dynamicCast!(inout T)(o))
6637                 return d;
6638             else
6639                 break;
6640         } while (o);
6641         return null;
6642     }
6643 }
6644 
6645 /// ditto
6646 template unwrap(Target)
6647 if (!isMutable!Target)
6648 {
6649     alias unwrap = .unwrap!(Unqual!Target);
6650 }
6651 
6652 ///
6653 @system unittest
6654 {
6655     interface Quack
6656     {
6657         int quack();
6658         @property int height();
6659     }
6660     interface Flyer
6661     {
6662         @property int height();
6663     }
6664     class Duck : Quack
6665     {
6666         int quack() { return 1; }
6667         @property int height() { return 10; }
6668     }
6669     class Human
6670     {
6671         int quack() { return 2; }
6672         @property int height() { return 20; }
6673     }
6674 
6675     Duck d1 = new Duck();
6676     Human h1 = new Human();
6677 
6678     interface Refleshable
6679     {
6680         int reflesh();
6681     }
6682 
6683     // does not have structural conformance
6684     static assert(!__traits(compiles, d1.wrap!Refleshable));
6685     static assert(!__traits(compiles, h1.wrap!Refleshable));
6686 
6687     // strict upcast
6688     Quack qd = d1.wrap!Quack;
6689     assert(qd is d1);
6690     assert(qd.quack() == 1);    // calls Duck.quack
6691     // strict downcast
6692     Duck d2 = qd.unwrap!Duck;
6693     assert(d2 is d1);
6694 
6695     // structural upcast
6696     Quack qh = h1.wrap!Quack;
6697     assert(qh.quack() == 2);    // calls Human.quack
6698     // structural downcast
6699     Human h2 = qh.unwrap!Human;
6700     assert(h2 is h1);
6701 
6702     // structural upcast (two steps)
6703     Quack qx = h1.wrap!Quack;   // Human -> Quack
6704     Flyer fx = qx.wrap!Flyer;   // Quack -> Flyer
6705     assert(fx.height == 20);    // calls Human.height
6706     // structural downcast (two steps)
6707     Quack qy = fx.unwrap!Quack; // Flyer -> Quack
6708     Human hy = qy.unwrap!Human; // Quack -> Human
6709     assert(hy is h1);
6710     // structural downcast (one step)
6711     Human hz = fx.unwrap!Human; // Flyer -> Human
6712     assert(hz is h1);
6713 }
6714 
6715 ///
6716 @system unittest
6717 {
6718     import std.traits : FunctionAttribute, functionAttributes;
6719     interface A { int run(); }
6720     interface B { int stop(); @property int status(); }
6721     class X
6722     {
6723         int run() { return 1; }
6724         int stop() { return 2; }
6725         @property int status() { return 3; }
6726     }
6727 
6728     auto x = new X();
6729     auto ab = x.wrap!(A, B);
6730     A a = ab;
6731     B b = ab;
6732     assert(a.run() == 1);
6733     assert(b.stop() == 2);
6734     assert(b.status == 3);
6735     static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
6736 }
6737 
6738 // Internal class to support dynamic cross-casting
6739 private interface Structural
6740 {
6741     inout(Object) _wrap_getSource() inout @safe pure nothrow;
6742 }
6743 
6744 @system unittest
6745 {
6746     class A
6747     {
6748         int draw()              { return 1; }
6749         int draw(int v)         { return v; }
6750 
6751         int draw() const        { return 2; }
6752         int draw() shared       { return 3; }
6753         int draw() shared const { return 4; }
6754         int draw() immutable    { return 5; }
6755     }
6756     interface Drawable
6757     {
6758         int draw();
6759         int draw() const;
6760         int draw() shared;
6761         int draw() shared const;
6762         int draw() immutable;
6763     }
6764     interface Drawable2
6765     {
6766         int draw(int v);
6767     }
6768 
6769     auto ma = new A();
6770     auto sa = new shared A();
6771     auto ia = new immutable A();
6772     {
6773                      Drawable  md = ma.wrap!Drawable;
6774                const Drawable  cd = ma.wrap!Drawable;
6775               shared Drawable  sd = sa.wrap!Drawable;
6776         shared const Drawable scd = sa.wrap!Drawable;
6777            immutable Drawable  id = ia.wrap!Drawable;
6778         assert( md.draw() == 1);
6779         assert( cd.draw() == 2);
6780         assert( sd.draw() == 3);
6781         assert(scd.draw() == 4);
6782         assert( id.draw() == 5);
6783     }
6784     {
6785         Drawable2 d = ma.wrap!Drawable2;
6786         static assert(!__traits(compiles, d.draw()));
6787         assert(d.draw(10) == 10);
6788     }
6789 }
6790 
6791 // https://issues.dlang.org/show_bug.cgi?id=10377
6792 @system unittest
6793 {
6794     import std.range, std.algorithm;
6795 
6796     interface MyInputRange(T)
6797     {
6798         @property T front();
6799         void popFront();
6800         @property bool empty();
6801     }
6802 
6803     //auto o = iota(0,10,1).inputRangeObject();
6804     //pragma(msg, __traits(allMembers, typeof(o)));
6805     auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)();
6806     assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
6807 }
6808 
6809 // https://issues.dlang.org/show_bug.cgi?id=10536
6810 @system unittest
6811 {
6812     interface Interface
6813     {
6814         int foo();
6815     }
6816     class Pluggable
6817     {
6818         int foo() { return 1; }
6819         @disable void opCast(T, this X)();  // !
6820     }
6821 
6822     Interface i = new Pluggable().wrap!Interface;
6823     assert(i.foo() == 1);
6824 }
6825 @system unittest
6826 {
6827     // Enhancement 10538
6828     interface Interface
6829     {
6830         int foo();
6831         int bar(int);
6832     }
6833     class Pluggable
6834     {
6835         int opDispatch(string name, A...)(A args) { return 100; }
6836     }
6837 
6838     Interface i = wrap!Interface(new Pluggable());
6839     assert(i.foo() == 100);
6840     assert(i.bar(10) == 100);
6841 }
6842 
6843 // https://issues.dlang.org/show_bug.cgi?id=12064
6844 @system unittest
6845 {
6846     interface I
6847     {
6848         int foo();
6849         final int nvi1(){return foo();}
6850     }
6851 
6852     interface J
6853     {
6854         int bar();
6855         final int nvi2(){return bar();}
6856     }
6857 
6858     class Baz
6859     {
6860         int foo() { return 42;}
6861         int bar() { return 12064;}
6862     }
6863 
6864     auto baz = new Baz();
6865     auto foobar = baz.wrap!(I, J)();
6866     assert(foobar.nvi1 == 42);
6867     assert(foobar.nvi2 == 12064);
6868 }
6869 
6870 // Make a tuple of non-static function symbols
6871 package template GetOverloadedMethods(T)
6872 {
6873     import std.meta : Filter;
6874 
6875     alias allMembers = __traits(allMembers, T);
6876     template follows(size_t i = 0)
6877     {
6878         static if (i >= allMembers.length)
6879         {
6880             alias follows = AliasSeq!();
6881         }
6882         else static if (!__traits(compiles, mixin("T."~allMembers[i])))
6883         {
6884             alias follows = follows!(i + 1);
6885         }
6886         else
6887         {
6888             enum name = allMembers[i];
6889 
6890             template isMethod(alias f)
6891             {
6892                 static if (is(typeof(&f) F == F*) && is(F == function))
6893                     enum isMethod = !__traits(isStaticFunction, f);
6894                 else
6895                     enum isMethod = false;
6896             }
6897             alias follows = AliasSeq!(
6898                 Filter!(isMethod, __traits(getOverloads, T, name)),
6899                 follows!(i + 1));
6900         }
6901     }
6902     alias GetOverloadedMethods = follows!();
6903 }
6904 // find a function from Fs that has same identifier and covariant type with f
6905 private template findCovariantFunction(alias finfo, Source, Fs...)
6906 {
6907     template check(size_t i = 0)
6908     {
6909         static if (i >= Fs.length)
6910             enum ptrdiff_t check = -1;
6911         else
6912         {
6913             enum ptrdiff_t check =
6914                 (finfo.name == __traits(identifier, Fs[i])) &&
6915                 isCovariantWith!(FunctionTypeOf!(Fs[i]), finfo.type)
6916               ? i : check!(i + 1);
6917         }
6918     }
6919     enum x = check!();
6920     static if (x == -1 && is(typeof(Source.opDispatch)))
6921     {
6922         alias Params = Parameters!(finfo.type);
6923         enum ptrdiff_t findCovariantFunction =
6924             is(typeof((             Source).init.opDispatch!(finfo.name)(Params.init))) ||
6925             is(typeof((       const Source).init.opDispatch!(finfo.name)(Params.init))) ||
6926             is(typeof((   immutable Source).init.opDispatch!(finfo.name)(Params.init))) ||
6927             is(typeof((      shared Source).init.opDispatch!(finfo.name)(Params.init))) ||
6928             is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init)))
6929           ? ptrdiff_t.max : -1;
6930     }
6931     else
6932         enum ptrdiff_t findCovariantFunction = x;
6933 }
6934 
6935 private enum TypeModifier
6936 {
6937     mutable     = 0,    // type is mutable
6938     const_      = 1,    // type is const
6939     immutable_  = 2,    // type is immutable
6940     shared_     = 4,    // type is shared
6941     inout_      = 8,    // type is wild
6942 }
6943 private template TypeMod(T)
6944 {
6945     static if (is(T == immutable))
6946     {
6947         enum mod1 = TypeModifier.immutable_;
6948         enum mod2 = 0;
6949     }
6950     else
6951     {
6952         enum mod1 = is(T == shared) ? TypeModifier.shared_ : 0;
6953         static if (is(T == const))
6954             enum mod2 = TypeModifier.const_;
6955         else static if (is(T == inout))
6956             enum mod2 = TypeModifier.inout_;
6957         else
6958             enum mod2 = TypeModifier.mutable;
6959     }
6960     enum TypeMod = cast(TypeModifier)(mod1 | mod2);
6961 }
6962 
6963 @system unittest
6964 {
6965     template UnittestFuncInfo(alias f)
6966     {
6967         enum name = __traits(identifier, f);
6968         alias type = FunctionTypeOf!f;
6969     }
6970 
6971     class A
6972     {
6973         int draw() { return 1; }
6974         @property int value() { return 2; }
6975         final int run() { return 3; }
6976     }
6977     alias methods = GetOverloadedMethods!A;
6978 
6979     alias int F1();
6980     alias @property int F2();
6981     alias string F3();
6982     alias nothrow @trusted uint F4();
6983     alias int F5(Object);
6984     alias bool F6(Object);
6985     static assert(methods.length == 3 + 4);
6986     static assert(__traits(identifier, methods[0]) == "draw"     && is(typeof(&methods[0]) == F1*));
6987     static assert(__traits(identifier, methods[1]) == "value"    && is(typeof(&methods[1]) == F2*));
6988     static assert(__traits(identifier, methods[2]) == "run"      && is(typeof(&methods[2]) == F1*));
6989 
6990     int draw();
6991     @property int value();
6992     void opEquals();
6993     int nomatch();
6994     static assert(findCovariantFunction!(UnittestFuncInfo!draw,     A, methods) == 0);
6995     static assert(findCovariantFunction!(UnittestFuncInfo!value,    A, methods) == 1);
6996     static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1);
6997     static assert(findCovariantFunction!(UnittestFuncInfo!nomatch,  A, methods) == -1);
6998 
6999     // considering opDispatch
7000     class B
7001     {
7002         void opDispatch(string name, A...)(A) {}
7003     }
7004     alias methodsB = GetOverloadedMethods!B;
7005     static assert(findCovariantFunction!(UnittestFuncInfo!draw,     B, methodsB) == ptrdiff_t.max);
7006     static assert(findCovariantFunction!(UnittestFuncInfo!value,    B, methodsB) == ptrdiff_t.max);
7007     static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max);
7008     static assert(findCovariantFunction!(UnittestFuncInfo!nomatch,  B, methodsB) == ptrdiff_t.max);
7009 }
7010 
7011 package template DerivedFunctionType(T...)
7012 {
7013     static if (!T.length)
7014     {
7015         alias DerivedFunctionType = void;
7016     }
7017     else static if (T.length == 1)
7018     {
7019         static if (is(T[0] == function))
7020         {
7021             alias DerivedFunctionType = T[0];
7022         }
7023         else
7024         {
7025             alias DerivedFunctionType = void;
7026         }
7027     }
7028     else static if (is(T[0] P0 == function) && is(T[1] P1 == function))
7029     {
7030         alias FA = FunctionAttribute;
7031 
7032         alias F0 = T[0], R0 = ReturnType!F0, PSTC0 = ParameterStorageClassTuple!F0;
7033         alias F1 = T[1], R1 = ReturnType!F1, PSTC1 = ParameterStorageClassTuple!F1;
7034         enum FA0 = functionAttributes!F0;
7035         enum FA1 = functionAttributes!F1;
7036 
7037         template CheckParams(size_t i = 0)
7038         {
7039             static if (i >= P0.length)
7040                 enum CheckParams = true;
7041             else
7042             {
7043                 enum CheckParams = (is(P0[i] == P1[i]) && PSTC0[i] == PSTC1[i]) &&
7044                                    CheckParams!(i + 1);
7045             }
7046         }
7047         static if (R0.sizeof == R1.sizeof && !is(CommonType!(R0, R1) == void) &&
7048                    P0.length == P1.length && CheckParams!() && TypeMod!F0 == TypeMod!F1 &&
7049                    variadicFunctionStyle!F0 == variadicFunctionStyle!F1 &&
7050                    functionLinkage!F0 == functionLinkage!F1 &&
7051                    ((FA0 ^ FA1) & (FA.ref_ | FA.property)) == 0)
7052         {
7053             alias R = Select!(is(R0 : R1), R0, R1);
7054             alias FX = FunctionTypeOf!(R function(P0));
7055             // @system is default
7056             alias FY = SetFunctionAttributes!(FX, functionLinkage!F0, (FA0 | FA1) & ~FA.system);
7057             alias DerivedFunctionType = DerivedFunctionType!(FY, T[2 .. $]);
7058         }
7059         else
7060             alias DerivedFunctionType = void;
7061     }
7062     else
7063         alias DerivedFunctionType = void;
7064 }
7065 @safe unittest
7066 {
7067     // attribute covariance
7068     alias int F1();
7069     static assert(is(DerivedFunctionType!(F1, F1) == F1));
7070     alias int F2() pure nothrow;
7071     static assert(is(DerivedFunctionType!(F1, F2) == F2));
7072     alias int F3() @safe;
7073     alias int F23() @safe pure nothrow;
7074     static assert(is(DerivedFunctionType!(F2, F3) == F23));
7075 
7076     // return type covariance
7077     alias long F4();
7078     static assert(is(DerivedFunctionType!(F1, F4) == void));
7079     class C {}
7080     class D : C {}
7081     alias C F5();
7082     alias D F6();
7083     static assert(is(DerivedFunctionType!(F5, F6) == F6));
7084     alias typeof(null) F7();
7085     alias int[] F8();
7086     alias int* F9();
7087     static assert(is(DerivedFunctionType!(F5, F7) == F7));
7088     static assert(is(DerivedFunctionType!(F7, F8) == void));
7089     static assert(is(DerivedFunctionType!(F7, F9) == F7));
7090 
7091     // variadic type equality
7092     alias int F10(int);
7093     alias int F11(int...);
7094     alias int F12(int, ...);
7095     static assert(is(DerivedFunctionType!(F10, F11) == void));
7096     static assert(is(DerivedFunctionType!(F10, F12) == void));
7097     static assert(is(DerivedFunctionType!(F11, F12) == void));
7098 
7099     // linkage equality
7100     alias extern(C) int F13(int);
7101     alias extern(D) int F14(int);
7102     alias extern(Windows) int F15(int);
7103     static assert(is(DerivedFunctionType!(F13, F14) == void));
7104     static assert(is(DerivedFunctionType!(F13, F15) == void));
7105     static assert(is(DerivedFunctionType!(F14, F15) == void));
7106 
7107     // ref & @property equality
7108     alias int F16(int);
7109     alias ref int F17(int);
7110     alias @property int F18(int);
7111     static assert(is(DerivedFunctionType!(F16, F17) == void));
7112     static assert(is(DerivedFunctionType!(F16, F18) == void));
7113     static assert(is(DerivedFunctionType!(F17, F18) == void));
7114 }
7115 
7116 package template Bind(alias Template, args1...)
7117 {
7118     alias Bind(args2...) = Template!(args1, args2);
7119 }
7120 
7121 
7122 /**
7123 Options regarding auto-initialization of a `SafeRefCounted` object (see
7124 the definition of `SafeRefCounted` below).
7125  */
7126 enum RefCountedAutoInitialize
7127 {
7128     /// Do not auto-initialize the object
7129     no,
7130     /// Auto-initialize the object
7131     yes,
7132 }
7133 
7134 ///
7135 @system unittest
7136 {
7137     import core.exception : AssertError;
7138     import std.exception : assertThrown;
7139 
7140     struct Foo
7141     {
7142         int a = 42;
7143     }
7144 
7145     SafeRefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
7146     SafeRefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
7147 
7148     assert(rcAuto.refCountedPayload.a == 42);
7149 
7150     assertThrown!AssertError(rcNoAuto.refCountedPayload);
7151     rcNoAuto.refCountedStore.ensureInitialized;
7152     assert(rcNoAuto.refCountedPayload.a == 42);
7153 }
7154 
7155 // Same the above but for old RefCounted and not documented
7156 @system unittest
7157 {
7158     import core.exception : AssertError;
7159     import std.exception : assertThrown;
7160 
7161     struct Foo
7162     {
7163         int a = 42;
7164     }
7165 
7166     RefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
7167     RefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
7168 
7169     assert(rcAuto.refCountedPayload.a == 42);
7170 
7171     assertThrown!AssertError(rcNoAuto.refCountedPayload);
7172     rcNoAuto.refCountedStore.ensureInitialized;
7173     assert(rcNoAuto.refCountedPayload.a == 42);
7174 }
7175 
7176 /**
7177 Defines a reference-counted object containing a `T` value as
7178 payload.
7179 
7180 An instance of `SafeRefCounted` is a reference to a structure,
7181 which is referred to as the $(I store), or $(I storage implementation
7182 struct) in this documentation.  The store contains a reference count
7183 and the `T` payload.  `SafeRefCounted` uses `malloc` to allocate
7184 the store.  As instances of `SafeRefCounted` are copied or go out of
7185 scope, they will automatically increment or decrement the reference
7186 count.  When the reference count goes down to zero, `SafeRefCounted`
7187 will call `destroy` against the payload and call `free` to
7188 deallocate the store.  If the `T` payload contains any references
7189 to GC-allocated memory, then `SafeRefCounted` will add it to the GC memory
7190 that is scanned for pointers, and remove it from GC scanning before
7191 `free` is called on the store.
7192 
7193 One important consequence of `destroy` is that it will call the
7194 destructor of the `T` payload.  GC-managed references are not
7195 guaranteed to be valid during a destructor call, but other members of
7196 `T`, such as file handles or pointers to `malloc` memory, will
7197 still be valid during the destructor call.  This allows the `T` to
7198 deallocate or clean up any non-GC resources immediately after the
7199 reference count has reached zero.
7200 
7201 Without -preview=dip1000, `SafeRefCounted` is unsafe and should be
7202 used with care. No references to the payload should be escaped outside
7203 the `SafeRefCounted` object.
7204 
7205 With -preview=dip1000, `SafeRefCounted` is safe if it's payload is accessed only
7206 with the $(LREF borrow) function. Scope semantics can also prevent accidental
7207 escaping of `refCountedPayload`, but it's still up to the user to not destroy
7208 the last counted reference while the payload is in use. Due to that,
7209 `refCountedPayload` remains accessible only in `@system` code.
7210 
7211 The `autoInit` option makes the object ensure the store is
7212 automatically initialized. Leaving $(D autoInit ==
7213 RefCountedAutoInitialize.yes) (the default option) is convenient but
7214 has the cost of a test whenever the payload is accessed. If $(D
7215 autoInit == RefCountedAutoInitialize.no), user code must call either
7216 `refCountedStore.isInitialized` or `refCountedStore.ensureInitialized`
7217 before attempting to access the payload. Not doing so results in null
7218 pointer dereference.
7219 
7220 If `T.this()` is annotated with `@disable` then `autoInit` must be
7221 `RefCountedAutoInitialize.no` in order to compile.
7222 
7223 See_Also:
7224   $(LREF RefCounted)
7225  */
7226 struct SafeRefCounted(T, RefCountedAutoInitialize autoInit =
7227         RefCountedAutoInitialize.yes)
7228 if (!is(T == class) && !(is(T == interface)))
7229 {
7230     version (D_BetterC)
7231     {
7232         private enum enableGCScan = false;
7233     }
7234     else
7235     {
7236         private enum enableGCScan = hasIndirections!T;
7237     }
7238 
7239     extern(C) private pure nothrow @nogc static
7240     {
7241         pragma(mangle, "free") void pureFree( void *ptr );
7242         static if (enableGCScan)
7243             import core.memory : GC;
7244     }
7245 
7246     pragma(inline, true) private void checkInit()()
7247     if (autoInit == RefCountedAutoInitialize.yes)
7248     {
7249         _refCounted.ensureInitialized();
7250     }
7251 
7252     pragma(inline, true) private void checkInit()() inout
7253     if (autoInit == RefCountedAutoInitialize.no)
7254     {
7255         assert(_refCounted.isInitialized,
7256             "Attempted to use an uninitialized payload.");
7257     }
7258 
7259     /// `SafeRefCounted` storage implementation.
7260     struct RefCountedStore
7261     {
7262         private struct Impl
7263         {
7264             T _payload;
7265             size_t _count;
7266         }
7267 
7268         private Impl* _store;
7269 
7270         private void initialize(A...)(auto ref A args)
7271         {
7272             import core.lifetime : emplace, forward;
7273 
7274             allocateStore();
7275             version (D_Exceptions) scope(failure) () @trusted { deallocateStore(); }();
7276             emplace(&_store._payload, forward!args);
7277             _store._count = 1;
7278         }
7279 
7280         private void move(ref T source) nothrow pure
7281         {
7282             import std.algorithm.mutation : moveEmplace;
7283 
7284             allocateStore();
7285             () @trusted { moveEmplace(source, _store._payload); }();
7286             _store._count = 1;
7287         }
7288 
7289         // 'nothrow': can only generate an Error
7290         private void allocateStore() nothrow pure
7291         {
7292             static if (enableGCScan)
7293             {
7294                 import std.internal.memory : enforceCalloc;
7295                 auto ptr = enforceCalloc(1, Impl.sizeof);
7296                 _store = () @trusted { return cast(Impl*) ptr; }();
7297                 () @trusted { GC.addRange(&_store._payload, T.sizeof); }();
7298             }
7299             else
7300             {
7301                 import std.internal.memory : enforceMalloc;
7302                 auto ptr = enforceMalloc(Impl.sizeof);
7303                 _store = () @trusted { return cast(Impl*) ptr; }();
7304             }
7305         }
7306 
7307         private void deallocateStore() nothrow pure
7308         {
7309             static if (enableGCScan)
7310             {
7311                 GC.removeRange(&this._store._payload);
7312             }
7313             pureFree(_store);
7314             _store = null;
7315         }
7316 
7317         /**
7318            Returns `true` if and only if the underlying store has been
7319            allocated and initialized.
7320         */
7321         @property nothrow @safe pure @nogc
7322         bool isInitialized() const
7323         {
7324             return _store !is null;
7325         }
7326 
7327         /**
7328            Returns underlying reference count if it is allocated and initialized
7329            (a positive integer), and `0` otherwise.
7330         */
7331         @property nothrow @safe pure @nogc
7332         size_t refCount() const
7333         {
7334             return isInitialized ? _store._count : 0;
7335         }
7336 
7337         /**
7338            Makes sure the payload was properly initialized. Such a
7339            call is typically inserted before using the payload.
7340 
7341            This function is unavailable if `T.this()` is annotated with
7342            `@disable`.
7343         */
7344         @safe pure nothrow
7345         void ensureInitialized()()
7346         {
7347             // By checking for `@disable this()` and failing early we can
7348             // produce a clearer error message.
7349             static assert(__traits(compiles, { static T t; }),
7350                 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
7351                 "` because `" ~ fullyQualifiedName!T ~
7352                 ".this()` is annotated with `@disable`.");
7353             if (!isInitialized) initialize();
7354         }
7355 
7356     }
7357     RefCountedStore _refCounted;
7358 
7359     /// Returns storage implementation struct.
7360     @property nothrow @safe
7361     ref inout(RefCountedStore) refCountedStore() inout
7362     {
7363         return _refCounted;
7364     }
7365 
7366 /**
7367 Constructor that initializes the payload.
7368 
7369 Postcondition: `refCountedStore.isInitialized`
7370  */
7371     this(A...)(auto ref A args) if (A.length > 0)
7372     out
7373     {
7374         assert(refCountedStore.isInitialized);
7375     }
7376     do
7377     {
7378         import core.lifetime : forward;
7379         _refCounted.initialize(forward!args);
7380     }
7381 
7382     /// Ditto
7383     this(return scope T val)
7384     {
7385         _refCounted.move(val);
7386     }
7387 
7388 /**
7389 Constructor that tracks the reference count appropriately. If $(D
7390 !refCountedStore.isInitialized), does nothing.
7391  */
7392     this(this) @safe pure nothrow @nogc
7393     {
7394         if (!_refCounted.isInitialized) return;
7395         ++_refCounted._store._count;
7396     }
7397 
7398 /**
7399 Destructor that tracks the reference count appropriately. If $(D
7400 !refCountedStore.isInitialized), does nothing. When the reference count goes
7401 down to zero, calls `destroy` agaist the payload and calls `free`
7402 to deallocate the corresponding resource.
7403  */
7404     ~this()
7405     {
7406         import std.traits : dip1000Enabled;
7407 
7408         // This prevents the same reference from decrementing the count twice.
7409         scope(exit) _refCounted = _refCounted.init;
7410 
7411         if (!_refCounted.isInitialized) return;
7412         assert(_refCounted._store._count > 0);
7413         if (--_refCounted._store._count) return;
7414         // Done, destroy and deallocate
7415         .destroy(_refCounted._store._payload);
7416 
7417         static if (dip1000Enabled)
7418         {
7419             () @trusted { _refCounted.deallocateStore(); }();
7420         }
7421         else _refCounted.deallocateStore();
7422     }
7423 
7424 /**
7425 Assignment operators.
7426 
7427 Note: You may not assign a new payload to an uninitialized SafeRefCounted, if
7428 auto initialization is off. Assigning another counted reference is still okay.
7429 */
7430     void opAssign(typeof(this) rhs)
7431     {
7432         import std.algorithm.mutation : swap;
7433 
7434         swap(_refCounted._store, rhs._refCounted._store);
7435     }
7436 
7437 /// Ditto
7438     void opAssign(T rhs)
7439     {
7440         import std.algorithm.mutation : move;
7441 
7442         checkInit();
7443         move(rhs, _refCounted._store._payload);
7444     }
7445 
7446     //version to have a single properly ddoc'ed function (w/ correct sig)
7447     version (StdDdoc)
7448     {
7449         /**
7450         Returns a reference to the payload. If (autoInit ==
7451         RefCountedAutoInitialize.yes), calls $(D
7452         refCountedStore.ensureInitialized). Otherwise, just issues $(D
7453         assert(refCountedStore.isInitialized)). Used with $(D alias
7454         refCountedPayload this;), so callers can just use the `SafeRefCounted`
7455         object as a `T`.
7456 
7457         $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
7458         So if $(D autoInit == RefCountedAutoInitialize.no)
7459         or called for a constant or immutable object, then
7460         `refCountedPayload` will also be qualified as nothrow
7461         (but will still assert if not initialized).
7462          */
7463         @property @system
7464         ref T refCountedPayload() return;
7465 
7466         /// ditto
7467         @property nothrow @system pure @nogc
7468         ref inout(T) refCountedPayload() inout return;
7469     }
7470     else
7471     {
7472         static if (autoInit == RefCountedAutoInitialize.yes)
7473         {
7474             //Can't use inout here because of potential mutation
7475             @property @system
7476             ref T refCountedPayload() return
7477             {
7478                 checkInit();
7479                 return _refCounted._store._payload;
7480             }
7481         }
7482         else
7483         {
7484             @property nothrow @system pure @nogc
7485             ref inout(T) refCountedPayload() inout return
7486             {
7487                 checkInit();
7488                 return _refCounted._store._payload;
7489             }
7490         }
7491     }
7492 
7493 /**
7494 Returns a reference to the payload. If (autoInit ==
7495 RefCountedAutoInitialize.yes), calls $(D
7496 refCountedStore.ensureInitialized). Otherwise, just issues $(D
7497 assert(refCountedStore.isInitialized)).
7498  */
7499     alias refCountedPayload this;
7500 
7501     static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
7502     {
7503         string toString(this This)()
7504         {
7505             import std.conv : to;
7506 
7507             static if (autoInit)
7508                 return to!string(refCountedPayload);
7509             else
7510             {
7511                 if (!_refCounted.isInitialized)
7512                     return This.stringof ~ "(RefCountedStore(null))";
7513                 else
7514                     return to!string(_refCounted._store._payload);
7515             }
7516         }
7517     }
7518 }
7519 
7520 ///
7521 @betterC pure @system nothrow @nogc unittest
7522 {
7523     // A pair of an `int` and a `size_t` - the latter being the
7524     // reference count - will be dynamically allocated
7525     auto rc1 = SafeRefCounted!int(5);
7526     assert(rc1 == 5);
7527     // No more allocation, add just one extra reference count
7528     auto rc2 = rc1;
7529     // Reference semantics
7530     rc2 = 42;
7531     assert(rc1 == 42);
7532     // the pair will be freed when rc1 and rc2 go out of scope
7533 }
7534 
7535 // This test can't be betterC because the test extractor won't see the private
7536 // `initialize` method accessed here
7537 pure @safe nothrow @nogc unittest
7538 {
7539     auto rc1 = SafeRefCounted!(int, RefCountedAutoInitialize.no)(5);
7540     rc1._refCounted.initialize();
7541 }
7542 
7543 pure @system unittest
7544 {
7545     foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7546     {
7547         MyRefCounted!int* p;
7548         auto rc1 = MyRefCounted!int(5);
7549         p = &rc1;
7550         assert(rc1 == 5);
7551         assert(rc1._refCounted._store._count == 1);
7552         {
7553             auto rc2 = rc1;
7554             assert(rc1._refCounted._store._count == 2);
7555             // Reference semantics
7556             rc2 = 42;
7557             assert(rc1 == 42);
7558             rc2 = rc2;
7559             assert(rc2._refCounted._store._count == 2);
7560             rc1 = rc2;
7561             assert(rc1._refCounted._store._count == 2);
7562         }
7563         // Artificially end scope of rc1 by calling ~this() explicitly
7564         rc1.__xdtor();
7565         assert(p._refCounted._store == null);
7566 
7567         // [Safe]RefCounted as a member
7568         struct A
7569         {
7570             MyRefCounted!int x;
7571             this(int y)
7572             {
7573                 x._refCounted.initialize(y);
7574             }
7575             A copy()
7576             {
7577                 auto another = this;
7578                 return another;
7579             }
7580         }
7581         auto a = A(4);
7582         auto b = a.copy();
7583         assert(a.x._refCounted._store._count == 2,
7584                "https://issues.dlang.org/show_bug.cgi?id=4356 still unfixed");
7585    }
7586 }
7587 
7588 @betterC pure @safe nothrow @nogc unittest
7589 {
7590     import std.algorithm.mutation : swap;
7591 
7592     SafeRefCounted!int p1, p2;
7593     swap(p1, p2);
7594 }
7595 
7596 // Same as above but for old RefCounted and not @safe
7597 @betterC pure @system nothrow @nogc unittest
7598 {
7599     import std.algorithm.mutation : swap;
7600 
7601     RefCounted!int p1, p2;
7602     swap(p1, p2);
7603 }
7604 
7605 // https://issues.dlang.org/show_bug.cgi?id=6606
7606 @betterC @safe pure nothrow @nogc unittest
7607 {
7608     union U {
7609        size_t i;
7610        void* p;
7611     }
7612 
7613     struct S {
7614        U u;
7615     }
7616 
7617     alias SRC = SafeRefCounted!S;
7618 }
7619 
7620 // Same as above but for old RefCounted and not @safe
7621 @betterC @system pure nothrow @nogc unittest
7622 {
7623     union U {
7624        size_t i;
7625        void* p;
7626     }
7627 
7628     struct S {
7629        U u;
7630     }
7631 
7632     alias SRC = RefCounted!S;
7633 }
7634 
7635 // https://issues.dlang.org/show_bug.cgi?id=6436
7636 @betterC @system pure unittest
7637 {
7638     import std.meta : AliasSeq;
7639     struct S
7640     {
7641         this(int rval) { assert(rval == 1); }
7642         this(ref int lval) { assert(lval == 3); ++lval; }
7643     }
7644 
7645     foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7646     {
7647         auto s1 = MyRefCounted!S(1);
7648         int lval = 3;
7649         auto s2 = MyRefCounted!S(lval);
7650         assert(lval == 4);
7651     }
7652 }
7653 
7654 // gc_addRange coverage
7655 @betterC @safe pure unittest
7656 {
7657     struct S { int* p; }
7658 
7659     auto s = SafeRefCounted!S(null);
7660 }
7661 
7662 // Same as above but for old RefCounted and not @safe
7663 @betterC @system pure unittest
7664 {
7665     struct S { int* p; }
7666 
7667     auto s = RefCounted!S(null);
7668 }
7669 
7670 @betterC @system pure nothrow @nogc unittest
7671 {
7672     import std.meta : AliasSeq;
7673     foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7674     {
7675         MyRefCounted!int a;
7676         a = 5; //This should not assert
7677         assert(a == 5);
7678 
7679         MyRefCounted!int b;
7680         b = a; //This should not assert either
7681         assert(b == 5);
7682 
7683         MyRefCounted!(int*) c;
7684     }
7685 }
7686 
7687 // https://issues.dlang.org/show_bug.cgi?id=21638
7688 @betterC @system pure nothrow @nogc unittest
7689 {
7690     import std.meta : AliasSeq;
7691     static struct NoDefaultCtor
7692     {
7693         @disable this();
7694         this(int x) @nogc nothrow pure { this.x = x; }
7695         int x;
7696     }
7697 
7698     foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7699     {
7700         auto rc = MyRefCounted!(NoDefaultCtor, RefCountedAutoInitialize.no)(5);
7701         assert(rc.x == 5);
7702     }
7703 }
7704 
7705 // https://issues.dlang.org/show_bug.cgi?id=20502
7706 @system unittest
7707 {
7708     alias Types = AliasSeq!(SafeRefCounted, RefCounted);
7709     alias funcs = AliasSeq!(safeRefCounted, refCounted);
7710     static foreach (aliasI; 0 .. 2)
7711     {{
7712         alias MyRefCounted = Types[aliasI];
7713         alias myRefCounted = funcs[aliasI];
7714         import std.conv : to;
7715 
7716         // Check that string conversion is transparent for refcounted
7717         // structs that do not have either toString or alias this.
7718         static struct A { Object a; }
7719         auto a  = A(new Object());
7720         auto r = myRefCounted(a);
7721         assert(to!string(r) == to!string(a));
7722         assert(to!string(cast(const) r) == to!string(cast(const) a));
7723         // Check that string conversion is still transparent for refcounted
7724         // structs that have alias this.
7725         static struct B { int b; alias b this; }
7726         static struct C { B b; alias b this; }
7727         assert(to!string(myRefCounted(C(B(123)))) == to!string(C(B(123))));
7728         // https://issues.dlang.org/show_bug.cgi?id=22093
7729         // Check that uninitialized refcounted structs that previously could be
7730         // converted to strings still can be.
7731         alias R = typeof(r);
7732         R r2;
7733         cast(void) (((const ref R a) => to!string(a))(r2));
7734         cast(void) to!string(MyRefCounted!(A, RefCountedAutoInitialize.no).init);
7735     }}
7736 }
7737 
7738 // We tried to make `refCountedPayload` `@safe` in
7739 // https://github.com/dlang/phobos/pull/8368 . It proved impossible, but it may
7740 // be possible in the future. This test checks for false `@safe` issues we
7741 // encountered.
7742 @safe unittest
7743 {
7744     struct Container
7745     {
7746         int[] data;
7747     }
7748 
7749     int[] getArr1 (scope Container local)
7750     {
7751         // allowed because the argument is inferred as return scope.
7752         return local.data;
7753     }
7754 
7755     int[] getArr2 (scope Container local)
7756     {
7757         SafeRefCounted!Container rc = local;
7758         // Escapes a reference to expired reference counted struct
7759         // don't do this!
7760         return rc.refCountedPayload().data;
7761     }
7762 
7763     int destroyFirstAndUseLater()
7764     {
7765         auto rc = SafeRefCounted!int(123);
7766         int* ptr = &rc.refCountedPayload();
7767         destroy(rc);
7768         return *ptr;
7769     }
7770 
7771     // This is here mainly to test that safety gets inferred correctly for the
7772     // next tests
7773     static assert(isSafe!getArr1);
7774     // https://github.com/dlang/phobos/pull/8101#issuecomment-843017282
7775     // This got apparently fixed automatically by compiler updates.
7776     static assert(!isSafe!getArr2);
7777     // As of writing, this is the issue that is still preventing payload access
7778     // from being `@safe`
7779     static assert(!isSafe!destroyFirstAndUseLater);
7780 }
7781 
7782 /**
7783 Borrows the payload of $(LREF SafeRefCounted) for use in `fun`. Inferred as `@safe`
7784 if `fun` is `@safe` and does not escape a reference to the payload.
7785 The reference count will be incremented for the duration of the operation,
7786 so destroying the last reference will not leave dangling references in
7787 `fun`.
7788 
7789 Params:
7790   fun = A callable accepting the payload either by value or by reference.
7791   refCount = The counted reference to the payload.
7792 Returns:
7793   The return value of `fun`, if any. `ref` in the return value will be
7794   forwarded.
7795 Issues:
7796   For yet unknown reason, code that uses this function with UFCS syntax
7797   will not be inferred as `@safe`. It will still compile if the code is
7798   explicitly marked `@safe` and nothing in `fun` prevents that.
7799 */
7800 template borrow(alias fun)
7801 {
7802     import std.functional : unaryFun;
7803 
7804     auto ref borrow(RC)(RC refCount) if
7805     (
7806         isInstanceOf!(SafeRefCounted, RC)
7807         && is(typeof(unaryFun!fun(refCount.refCountedPayload)))
7808     )
7809     {
7810         refCount.checkInit();
7811 
7812         // If `fun` escapes a reference to the payload, it will be inferred
7813         // as unsafe due to the scope storage class here.
7814         scope plPtr = &refCount._refCounted._store._payload;
7815         return unaryFun!fun(*plPtr);
7816 
7817         // We destroy our copy of the reference here, automatically destroying
7818         // the payload if `fun` destroyed the last reference outside.
7819     }
7820 }
7821 
7822 /// This example can be marked `@safe` with `-preview=dip1000`.
7823 @safe pure nothrow unittest
7824 {
7825     auto rcInt = safeRefCounted(5);
7826     assert(rcInt.borrow!(theInt => theInt) == 5);
7827     auto sameInt = rcInt;
7828     assert(sameInt.borrow!"a" == 5);
7829 
7830     // using `ref` in the function
7831     auto arr = [0, 1, 2, 3, 4, 5, 6];
7832     sameInt.borrow!(ref (x) => arr[x]) = 10;
7833     assert(arr == [0, 1, 2, 3, 4, 10, 6]);
7834 
7835     // modifying the payload via an alias
7836     sameInt.borrow!"a*=2";
7837     assert(rcInt.borrow!"a" == 10);
7838 }
7839 
7840 // Some memory safety penetration testing.
7841 @system unittest
7842 {
7843     int* globalPtr;
7844     int torpedoesFired = 0;
7845     struct Destroyer { ~this() @safe { torpedoesFired++; } }
7846 
7847     alias RcInt = typeof(safeRefCounted(0));
7848     auto standardUsage(RcInt arg)
7849     {
7850         return borrow!((ref x) => x)(arg);
7851     }
7852     ref harmlessRefReturn(RcInt arg)
7853     {
7854         return borrow!(ref (ref x) => *globalPtr = x)(arg);
7855     }
7856     ref problematicRefReturn(RcInt arg)
7857     {
7858         return borrow!(ref (ref x) => x)(arg);
7859     }
7860     auto sideChannelEscape(RcInt arg)
7861     {
7862         return borrow!((ref x)
7863         {
7864             globalPtr = &x;
7865             return x;
7866         })(arg);
7867     }
7868     auto destroyDuringApply()
7869     {
7870         auto rc = safeRefCounted(Destroyer());
7871         return borrow!((ref x)
7872         {
7873             // Destroys the last reference to the payload, decrementing it's
7874             // reference count.
7875             rc.__dtor();
7876             // Destroy again! rc should be set to it's init value so that this
7877             // won't decrement the reference count of the original payload.
7878             rc.__dtor();
7879             // The internal reference count increment done for duration of
7880             // `apply` should make sure that the payload destructor is not yet
7881             // run, and this value thus not incremented.
7882             return torpedoesFired;
7883         })(rc);
7884     }
7885 
7886     // First, let's verify the dangerous functions really do what they are
7887     // supposed to do.
7888     auto testRc = safeRefCounted(42);
7889     assert(sideChannelEscape(testRc) == 42);
7890     assert(&problematicRefReturn(testRc) == globalPtr);
7891 
7892     // Now, are the @safe attributes inferred correctly?
7893     assert(isSafe!standardUsage);
7894     assert(isSafe!harmlessRefReturn);
7895     assert(!isSafe!problematicRefReturn);
7896     assert(!isSafe!sideChannelEscape);
7897     assert(isSafe!destroyDuringApply);
7898 
7899     // Finally, we test protection against early destruction during `apply`.
7900     auto torpedoesUpToReturn = destroyDuringApply();
7901     assert(torpedoesFired == torpedoesUpToReturn + 1);
7902 }
7903 
7904 /**
7905  * Initializes a `SafeRefCounted` with `val`. The template parameter
7906  * `T` of `SafeRefCounted` is inferred from `val`.
7907  * This function can be used to move non-copyable values to the heap.
7908  * It also disables the `autoInit` option of `SafeRefCounted`.
7909  *
7910  * Params:
7911  *   val = The value to be reference counted
7912  * Returns:
7913  *   An initialized `SafeRefCounted` containing `val`.
7914  * See_Also:
7915  *   $(LREF refCounted)
7916  *   $(HTTP en.cppreference.com/w/cpp/memory/shared_ptr/make_shared, C++'s make_shared)
7917  */
7918 SafeRefCounted!(T, RefCountedAutoInitialize.no) safeRefCounted(T)(T val)
7919 {
7920     typeof(return) res;
7921     res._refCounted.move(val);
7922     return res;
7923 }
7924 
7925 ///
7926 @system unittest
7927 {
7928     static struct File
7929     {
7930         static size_t nDestroyed;
7931         string name;
7932         @disable this(this); // not copyable
7933         ~this() { name = null; ++nDestroyed; }
7934     }
7935 
7936     auto file = File("name");
7937     assert(file.name == "name");
7938     // file cannot be copied and has unique ownership
7939     static assert(!__traits(compiles, {auto file2 = file;}));
7940 
7941     assert(File.nDestroyed == 0);
7942 
7943     // make the file ref counted to share ownership
7944     // Note:
7945     //   We write a compound statement (brace-delimited scope) in which all `SafeRefCounted!File` handles are created and deleted.
7946     //   This allows us to see (after the scope) what happens after all handles have been destroyed.
7947     {
7948         // We move the content of `file` to a separate (and heap-allocated) `File` object,
7949         // managed-and-accessed via one-or-multiple (initially: one) `SafeRefCounted!File` objects ("handles").
7950         // This "moving":
7951         //   (1) invokes `file`'s destructor (=> `File.nDestroyed` is incremented from 0 to 1 and `file.name` becomes `null`);
7952         //   (2) overwrites `file` with `File.init` (=> `file.name` becomes `null`).
7953         // It appears that writing `name = null;` in the destructor is redundant,
7954         // but please note that (2) is only performed if `File` defines a destructor (or post-blit operator),
7955         // and in the absence of the `nDestroyed` instrumentation there would have been no reason to define a destructor.
7956         import std.algorithm.mutation : move;
7957         auto rcFile = safeRefCounted(move(file));
7958         assert(rcFile.name == "name");
7959         assert(File.nDestroyed == 1);
7960         assert(file.name == null);
7961 
7962         // We create another `SafeRefCounted!File` handle to the same separate `File` object.
7963         // While any of the handles is still alive, the `File` object is kept alive (=> `File.nDestroyed` is not modified).
7964         auto rcFile2 = rcFile;
7965         assert(rcFile.refCountedStore.refCount == 2);
7966         assert(File.nDestroyed == 1);
7967     }
7968     // The separate `File` object is deleted when the last `SafeRefCounted!File` handle is destroyed
7969     // (i.e. at the closing brace of the compound statement above, which destroys both handles: `rcFile` and `rcFile2`)
7970     // (=> `File.nDestroyed` is incremented again, from 1 to 2):
7971     assert(File.nDestroyed == 2);
7972 }
7973 
7974 /**
7975     Creates a proxy for the value `a` that will forward all operations
7976     while disabling implicit conversions. The aliased item `a` must be
7977     an $(B lvalue). This is useful for creating a new type from the
7978     "base" type (though this is $(B not) a subtype-supertype
7979     relationship; the new type is not related to the old type in any way,
7980     by design).
7981 
7982     The new type supports all operations that the underlying type does,
7983     including all operators such as `+`, `--`, `<`, `[]`, etc.
7984 
7985     Params:
7986         a = The value to act as a proxy for all operations. It must
7987             be an lvalue.
7988  */
7989 mixin template Proxy(alias a)
7990 {
7991     private alias ValueType = typeof({ return a; }());
7992 
7993     /* Determine if 'T.a' can referenced via a const(T).
7994      * Use T* as the parameter because 'scope' inference needs a fully
7995      * analyzed T, which doesn't work when accessibleFrom() is used in a
7996      * 'static if' in the definition of Proxy or T.
7997      */
7998     private enum bool accessibleFrom(T) =
7999         is(typeof((T* self){ cast(void) mixin("(*self)."~__traits(identifier, a)); }));
8000 
8001     static if (is(typeof(this) == class))
8002     {
8003         override bool opEquals(Object o)
8004         {
8005             if (auto b = cast(typeof(this))o)
8006             {
8007                 return a == mixin("b."~__traits(identifier, a));
8008             }
8009             return false;
8010         }
8011 
8012         bool opEquals(T)(T b)
8013             if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
8014         {
8015             static if (is(typeof(a.opEquals(b))))
8016                 return a.opEquals(b);
8017             else static if (is(typeof(b.opEquals(a))))
8018                 return b.opEquals(a);
8019             else
8020                 return a == b;
8021         }
8022 
8023         override int opCmp(Object o)
8024         {
8025             if (auto b = cast(typeof(this))o)
8026             {
8027                 return a < mixin("b."~__traits(identifier, a)) ? -1
8028                      : a > mixin("b."~__traits(identifier, a)) ? +1 : 0;
8029             }
8030             static if (is(ValueType == class))
8031                 return a.opCmp(o);
8032             else
8033                 throw new Exception("Attempt to compare a "~typeid(this).toString~" and a "~typeid(o).toString);
8034         }
8035 
8036         int opCmp(T)(auto ref const T b)
8037             if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
8038         {
8039             static if (is(typeof(a.opCmp(b))))
8040                 return a.opCmp(b);
8041             else static if (is(typeof(b.opCmp(a))))
8042                 return -b.opCmp(a);
8043             else
8044                 return a < b ? -1 : a > b ? +1 : 0;
8045         }
8046 
8047         static if (accessibleFrom!(const typeof(this)))
8048         {
8049             override size_t toHash() const nothrow @safe
8050             {
8051                 static if (__traits(compiles, .hashOf(a)))
8052                     return .hashOf(a);
8053                 else
8054                 // Workaround for when .hashOf is not both @safe and nothrow.
8055                 {
8056                     static if (is(typeof(&a) == ValueType*))
8057                         alias v = a;
8058                     else
8059                         auto v = a; // if a is (property) function
8060                     // BUG: Improperly casts away `shared`!
8061                     return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
8062                 }
8063             }
8064         }
8065     }
8066     else
8067     {
8068         auto ref opEquals(this X, B)(auto ref B b)
8069         {
8070             static if (is(immutable B == immutable typeof(this)))
8071             {
8072                 return a == mixin("b."~__traits(identifier, a));
8073             }
8074             else
8075                 return a == b;
8076         }
8077 
8078         auto ref opCmp(this X, B)(auto ref B b)
8079         {
8080             static if (is(typeof(a.opCmp(b))))
8081                 return a.opCmp(b);
8082             else static if (is(typeof(b.opCmp(a))))
8083                 return -b.opCmp(a);
8084             else static if (isFloatingPoint!ValueType || isFloatingPoint!B)
8085                 return a < b ? -1 : a > b ? +1 : a == b ? 0 : float.nan;
8086             else
8087                 return a < b ? -1 : (a > b);
8088         }
8089 
8090         static if (accessibleFrom!(const typeof(this)))
8091         {
8092             size_t toHash() const nothrow @safe
8093             {
8094                 static if (__traits(compiles, .hashOf(a)))
8095                     return .hashOf(a);
8096                 else
8097                 // Workaround for when .hashOf is not both @safe and nothrow.
8098                 {
8099                     static if (is(typeof(&a) == ValueType*))
8100                         alias v = a;
8101                     else
8102                         auto v = a; // if a is (property) function
8103                     // BUG: Improperly casts away `shared`!
8104                     return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
8105                 }
8106             }
8107         }
8108     }
8109 
8110     auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
8111 
8112     auto ref opCast(T, this X)() { return cast(T) a; }
8113 
8114     auto ref opIndex(this X, D...)(auto ref D i)               { return a[i]; }
8115     auto ref opSlice(this X      )()                           { return a[]; }
8116     auto ref opSlice(this X, B, E)(auto ref B b, auto ref E e) { return a[b .. e]; }
8117 
8118     auto ref opUnary     (string op, this X      )()                           { return mixin(op~"a"); }
8119     auto ref opIndexUnary(string op, this X, D...)(auto ref D i)               { return mixin(op~"a[i]"); }
8120     auto ref opSliceUnary(string op, this X      )()                           { return mixin(op~"a[]"); }
8121     auto ref opSliceUnary(string op, this X, B, E)(auto ref B b, auto ref E e) { return mixin(op~"a[b .. e]"); }
8122 
8123     auto ref opBinary(string op, this X, B)(auto ref B b)
8124     if (op == "in" && is(typeof(a in b)) || op != "in")
8125     {
8126         return mixin("a "~op~" b");
8127     }
8128     auto ref opBinaryRight(string op, this X, B)(auto ref B b) { return mixin("b "~op~" a"); }
8129 
8130     static if (!is(typeof(this) == class))
8131     {
8132         import std.traits;
8133         static if (isAssignable!ValueType)
8134         {
8135             auto ref opAssign(this X)(auto ref typeof(this) v)
8136             {
8137                 a = mixin("v."~__traits(identifier, a));
8138                 return this;
8139             }
8140         }
8141         else
8142         {
8143             @disable void opAssign(this X)(auto ref typeof(this) v);
8144         }
8145     }
8146 
8147     auto ref opAssign     (this X, V      )(auto ref V v) if (!is(V == typeof(this))) { return a       = v; }
8148     auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i)               { return a[i]    = v; }
8149     auto ref opSliceAssign(this X, V      )(auto ref V v)                             { return a[]     = v; }
8150     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; }
8151 
8152     auto ref opOpAssign     (string op, this X, V      )(auto ref V v)
8153     {
8154         return mixin("a = a "~op~" v");
8155     }
8156     auto ref opIndexOpAssign(string op, this X, V, D...)(auto ref V v, auto ref D i)
8157     {
8158         return mixin("a[i] "   ~op~"= v");
8159     }
8160     auto ref opSliceOpAssign(string op, this X, V      )(auto ref V v)
8161     {
8162         return mixin("a[] "    ~op~"= v");
8163     }
8164     auto ref opSliceOpAssign(string op, this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e)
8165     {
8166         return mixin("a[b .. e] "~op~"= v");
8167     }
8168 
8169     template opDispatch(string name)
8170     {
8171         static if (is(typeof(__traits(getMember, a, name)) == function))
8172         {
8173             // non template function
8174             auto ref opDispatch(this X, Args...)(auto ref Args args) { return mixin("a."~name~"(args)"); }
8175         }
8176         else static if (is(typeof({ enum x = mixin("a."~name); })))
8177         {
8178             // built-in type field, manifest constant, and static non-mutable field
8179             enum opDispatch = mixin("a."~name);
8180         }
8181         else static if (__traits(isTemplate, mixin("a."~name)))
8182         {
8183             // member template
8184             template opDispatch(T...)
8185             {
8186                 enum targs = T.length ? "!T" : "";
8187                 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
8188             }
8189         }
8190         else
8191         {
8192             // field or property function
8193             @property auto ref opDispatch(this X)()                { return mixin("a."~name);        }
8194             @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
8195         }
8196 
8197     }
8198 
8199     import std.traits : isArray;
8200 
8201     static if (isArray!ValueType)
8202     {
8203         auto opDollar() const { return a.length; }
8204     }
8205     else static if (is(typeof(a.opDollar!0)))
8206     {
8207         auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
8208     }
8209     else static if (is(typeof(a.opDollar) == function))
8210     {
8211         auto ref opDollar() { return a.opDollar(); }
8212     }
8213     else static if (is(typeof(a.opDollar)))
8214     {
8215         alias opDollar = a.opDollar;
8216     }
8217 }
8218 
8219 ///
8220 @safe unittest
8221 {
8222     struct MyInt
8223     {
8224         private int value;
8225         mixin Proxy!value;
8226 
8227         this(int n){ value = n; }
8228     }
8229 
8230     MyInt n = 10;
8231 
8232     // Enable operations that original type has.
8233     ++n;
8234     assert(n == 11);
8235     assert(n * 2 == 22);
8236 
8237     void func(int n) { }
8238 
8239     // Disable implicit conversions to original type.
8240     //int x = n;
8241     //func(n);
8242 }
8243 
8244 ///The proxied value must be an $(B lvalue).
8245 @safe unittest
8246 {
8247     struct NewIntType
8248     {
8249         //Won't work; the literal '1'
8250         //is an rvalue, not an lvalue
8251         //mixin Proxy!1;
8252 
8253         //Okay, n is an lvalue
8254         int n;
8255         mixin Proxy!n;
8256 
8257         this(int n) { this.n = n; }
8258     }
8259 
8260     NewIntType nit = 0;
8261     nit++;
8262     assert(nit == 1);
8263 
8264 
8265     struct NewObjectType
8266     {
8267         Object obj;
8268         //Ok, obj is an lvalue
8269         mixin Proxy!obj;
8270 
8271         this (Object o) { obj = o; }
8272     }
8273 
8274     NewObjectType not = new Object();
8275     assert(__traits(compiles, not.toHash()));
8276 }
8277 
8278 /**
8279     There is one exception to the fact that the new type is not related to the
8280     old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
8281     functions are usable with the new type; they will be forwarded on to the
8282     proxied value.
8283  */
8284 @safe unittest
8285 {
8286     import std.math.traits : isInfinity;
8287 
8288     float f = 1.0;
8289     assert(!f.isInfinity);
8290 
8291     struct NewFloat
8292     {
8293         float _;
8294         mixin Proxy!_;
8295 
8296         this(float f) { _ = f; }
8297     }
8298 
8299     NewFloat nf = 1.0f;
8300     assert(!nf.isInfinity);
8301 }
8302 
8303 @safe unittest
8304 {
8305     static struct MyInt
8306     {
8307         private int value;
8308         mixin Proxy!value;
8309         this(int n) inout { value = n; }
8310 
8311         enum str = "str";
8312         static immutable arr = [1,2,3];
8313     }
8314 
8315     static foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
8316     {{
8317         T m = 10;
8318         static assert(!__traits(compiles, { int x = m; }));
8319         static assert(!__traits(compiles, { void func(int n){} func(m); }));
8320         assert(m == 10);
8321         assert(m != 20);
8322         assert(m < 20);
8323         assert(+m == 10);
8324         assert(-m == -10);
8325         assert(cast(double) m == 10.0);
8326         assert(m + 10 == 20);
8327         assert(m - 5 == 5);
8328         assert(m * 20 == 200);
8329         assert(m / 2 == 5);
8330         assert(10 + m == 20);
8331         assert(15 - m == 5);
8332         assert(20 * m == 200);
8333         assert(50 / m == 5);
8334         static if (is(T == MyInt))  // mutable
8335         {
8336             assert(++m == 11);
8337             assert(m++ == 11); assert(m == 12);
8338             assert(--m == 11);
8339             assert(m-- == 11); assert(m == 10);
8340             m = m;
8341             m = 20; assert(m == 20);
8342         }
8343         static assert(T.max == int.max);
8344         static assert(T.min == int.min);
8345         static assert(T.init == int.init);
8346         static assert(T.str == "str");
8347         static assert(T.arr == [1,2,3]);
8348     }}
8349 }
8350 @system unittest
8351 {
8352     static struct MyArray
8353     {
8354         private int[] value;
8355         mixin Proxy!value;
8356         this(int[] arr) { value = arr; }
8357         this(immutable int[] arr) immutable { value = arr; }
8358     }
8359 
8360     static foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
8361     {{
8362       static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
8363         T a = [1,2,3,4].idup;   // workaround until qualified ctor is properly supported
8364       else
8365         T a = [1,2,3,4];
8366         assert(a == [1,2,3,4]);
8367         assert(a != [5,6,7,8]);
8368         assert(+a[0]    == 1);
8369         version (LittleEndian)
8370             assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
8371         else
8372             assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
8373         assert(a ~ [10,11] == [1,2,3,4,10,11]);
8374         assert(a[0]    == 1);
8375         assert(a[]     == [1,2,3,4]);
8376         assert(a[2 .. 4] == [3,4]);
8377         static if (is(T == MyArray))    // mutable
8378         {
8379             a = a;
8380             a = [5,6,7,8];  assert(a == [5,6,7,8]);
8381             a[0]     = 0;   assert(a == [0,6,7,8]);
8382             a[]      = 1;   assert(a == [1,1,1,1]);
8383             a[0 .. 3]  = 2;   assert(a == [2,2,2,1]);
8384             a[0]    += 2;   assert(a == [4,2,2,1]);
8385             a[]     *= 2;   assert(a == [8,4,4,2]);
8386             a[0 .. 2] /= 2;   assert(a == [4,2,4,2]);
8387         }
8388     }}
8389 }
8390 @system unittest
8391 {
8392     class Foo
8393     {
8394         int field;
8395 
8396         @property int val1() const { return field; }
8397         @property void val1(int n) { field = n; }
8398 
8399         @property ref int val2() { return field; }
8400 
8401         int func(int x, int y) const { return x; }
8402         void func1(ref int a) { a = 9; }
8403 
8404         T ifti1(T)(T t) { return t; }
8405         void ifti2(Args...)(Args args) { }
8406         void ifti3(T, Args...)(Args args) { }
8407 
8408         T opCast(T)(){ return T.init; }
8409 
8410         T tempfunc(T)() { return T.init; }
8411     }
8412     class Hoge
8413     {
8414         Foo foo;
8415         mixin Proxy!foo;
8416         this(Foo f) { foo = f; }
8417     }
8418 
8419     auto h = new Hoge(new Foo());
8420     int n;
8421 
8422     static assert(!__traits(compiles, { Foo f = h; }));
8423 
8424     // field
8425     h.field = 1;            // lhs of assign
8426     n = h.field;            // rhs of assign
8427     assert(h.field == 1);   // lhs of BinExp
8428     assert(1 == h.field);   // rhs of BinExp
8429     assert(n == 1);
8430 
8431     // getter/setter property function
8432     h.val1 = 4;
8433     n = h.val1;
8434     assert(h.val1 == 4);
8435     assert(4 == h.val1);
8436     assert(n == 4);
8437 
8438     // ref getter property function
8439     h.val2 = 8;
8440     n = h.val2;
8441     assert(h.val2 == 8);
8442     assert(8 == h.val2);
8443     assert(n == 8);
8444 
8445     // member function
8446     assert(h.func(2,4) == 2);
8447     h.func1(n);
8448     assert(n == 9);
8449 
8450     // IFTI
8451     assert(h.ifti1(4) == 4);
8452     h.ifti2(4);
8453     h.ifti3!int(4, 3);
8454 
8455     // https://issues.dlang.org/show_bug.cgi?id=5896 test
8456     assert(h.opCast!int() == 0);
8457     assert(cast(int) h == 0);
8458     const ih = new const Hoge(new Foo());
8459     static assert(!__traits(compiles, ih.opCast!int()));
8460     static assert(!__traits(compiles, cast(int) ih));
8461 
8462     // template member function
8463     assert(h.tempfunc!int() == 0);
8464 }
8465 
8466 @system unittest // about Proxy inside a class
8467 {
8468     class MyClass
8469     {
8470         int payload;
8471         mixin Proxy!payload;
8472         this(int i){ payload = i; }
8473         string opCall(string msg){ return msg; }
8474         int pow(int i){ return payload ^^ i; }
8475     }
8476 
8477     class MyClass2
8478     {
8479         MyClass payload;
8480         mixin Proxy!payload;
8481         this(int i){ payload = new MyClass(i); }
8482     }
8483 
8484     class MyClass3
8485     {
8486         int payload;
8487         mixin Proxy!payload;
8488         this(int i){ payload = i; }
8489     }
8490 
8491     // opEquals
8492     Object a = new MyClass(5);
8493     Object b = new MyClass(5);
8494     Object c = new MyClass2(5);
8495     Object d = new MyClass3(5);
8496     assert(a == b);
8497     assert((cast(MyClass) a) == 5);
8498     assert(5 == (cast(MyClass) b));
8499     assert(5 == cast(MyClass2) c);
8500     assert(a != d);
8501 
8502     assert(c != a);
8503     // oops! above line is unexpected, isn't it?
8504     // the reason is below.
8505     // MyClass2.opEquals knows MyClass but,
8506     // MyClass.opEquals doesn't know MyClass2.
8507     // so, c.opEquals(a) is true, but a.opEquals(c) is false.
8508     // furthermore, opEquals(T) couldn't be invoked.
8509     assert((cast(MyClass2) c) != (cast(MyClass) a));
8510 
8511     // opCmp
8512     Object e = new MyClass2(7);
8513     assert(a < cast(MyClass2) e); // OK. and
8514     assert(e > a); // OK, but...
8515     // assert(a < e); // RUNTIME ERROR!
8516     // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
8517     assert(3 < cast(MyClass) a);
8518     assert((cast(MyClass2) e) < 11);
8519 
8520     // opCall
8521     assert((cast(MyClass2) e)("hello") == "hello");
8522 
8523     // opCast
8524     assert((cast(MyClass)(cast(MyClass2) c)) == a);
8525     assert((cast(int)(cast(MyClass2) c)) == 5);
8526 
8527     // opIndex
8528     class MyClass4
8529     {
8530         string payload;
8531         mixin Proxy!payload;
8532         this(string s){ payload = s; }
8533     }
8534     class MyClass5
8535     {
8536         MyClass4 payload;
8537         mixin Proxy!payload;
8538         this(string s){ payload = new MyClass4(s); }
8539     }
8540     auto f = new MyClass4("hello");
8541     assert(f[1] == 'e');
8542     auto g = new MyClass5("hello");
8543     assert(f[1] == 'e');
8544 
8545     // opSlice
8546     assert(f[2 .. 4] == "ll");
8547 
8548     // opUnary
8549     assert(-(cast(MyClass2) c) == -5);
8550 
8551     // opBinary
8552     assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
8553     assert(5 + cast(MyClass) a == 10);
8554 
8555     // opAssign
8556     (cast(MyClass2) c) = 11;
8557     assert((cast(MyClass2) c) == 11);
8558     (cast(MyClass2) c) = new MyClass(13);
8559     assert((cast(MyClass2) c) == 13);
8560 
8561     // opOpAssign
8562     assert((cast(MyClass2) c) += 4);
8563     assert((cast(MyClass2) c) == 17);
8564 
8565     // opDispatch
8566     assert((cast(MyClass2) c).pow(2) == 289);
8567 
8568     // opDollar
8569     assert(f[2..$-1] == "ll");
8570 
8571     // toHash
8572     int[Object] hash;
8573     hash[a] = 19;
8574     hash[c] = 21;
8575     assert(hash[b] == 19);
8576     assert(hash[c] == 21);
8577 }
8578 
8579 @safe unittest
8580 {
8581     struct MyInt
8582     {
8583         int payload;
8584 
8585         mixin Proxy!payload;
8586     }
8587 
8588     MyInt v;
8589     v = v;
8590 
8591     struct Foo
8592     {
8593         @disable void opAssign(typeof(this));
8594     }
8595     struct MyFoo
8596     {
8597         Foo payload;
8598 
8599         mixin Proxy!payload;
8600     }
8601     MyFoo f;
8602     static assert(!__traits(compiles, f = f));
8603 
8604     struct MyFoo2
8605     {
8606         Foo payload;
8607 
8608         mixin Proxy!payload;
8609 
8610         // override default Proxy behavior
8611         void opAssign(typeof(this) rhs){}
8612     }
8613     MyFoo2 f2;
8614     f2 = f2;
8615 }
8616 
8617 // https://issues.dlang.org/show_bug.cgi?id=8613
8618 @safe unittest
8619 {
8620     static struct Name
8621     {
8622         mixin Proxy!val;
8623         private string val;
8624         this(string s) { val = s; }
8625     }
8626 
8627     bool[Name] names;
8628     names[Name("a")] = true;
8629     bool* b = Name("a") in names;
8630 }
8631 
8632 // workaround for https://issues.dlang.org/show_bug.cgi?id=19669
8633 private enum isDIP1000 = __traits(compiles, () @safe {
8634      int x;
8635      int* p;
8636      p = &x;
8637 });
8638 // excludes struct S; it's 'mixin Proxy!foo' doesn't compile with -dip1000
8639 static if (isDIP1000) {} else
8640 @system unittest
8641 {
8642     // https://issues.dlang.org/show_bug.cgi?id=14213
8643     // using function for the payload
8644     static struct S
8645     {
8646         int foo() { return 12; }
8647         mixin Proxy!foo;
8648     }
8649     S s;
8650     assert(s + 1 == 13);
8651     assert(s * 2 == 24);
8652 }
8653 
8654 @system unittest
8655 {
8656     static class C
8657     {
8658         int foo() { return 12; }
8659         mixin Proxy!foo;
8660     }
8661     C c = new C();
8662 }
8663 
8664 // Check all floating point comparisons for both Proxy and Typedef,
8665 // also against int and a Typedef!int, to be as regression-proof
8666 // as possible. https://issues.dlang.org/show_bug.cgi?id=15561
8667 @safe unittest
8668 {
8669     static struct MyFloatImpl
8670     {
8671         float value;
8672         mixin Proxy!value;
8673     }
8674     static void allFail(T0, T1)(T0 a, T1 b)
8675     {
8676         assert(!(a == b));
8677         assert(!(a<b));
8678         assert(!(a <= b));
8679         assert(!(a>b));
8680         assert(!(a >= b));
8681     }
8682     static foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
8683         float, real, Typedef!int, int))
8684     {
8685         static foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
8686         {{
8687             T1 a;
8688             T2 b;
8689 
8690             static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
8691                 allFail(a, b);
8692             a = 3;
8693             allFail(a, b);
8694 
8695             b = 4;
8696             assert(a != b);
8697             assert(a<b);
8698             assert(a <= b);
8699             assert(!(a>b));
8700             assert(!(a >= b));
8701 
8702             a = 4;
8703             assert(a == b);
8704             assert(!(a<b));
8705             assert(a <= b);
8706             assert(!(a>b));
8707             assert(a >= b);
8708         }}
8709     }
8710 }
8711 
8712 /**
8713 $(B Typedef) allows the creation of a unique type which is
8714 based on an existing type. Unlike the `alias` feature,
8715 $(B Typedef) ensures the two types are not considered as equals.
8716 
8717 Params:
8718 
8719     init = Optional initial value for the new type.
8720     cookie = Optional, used to create multiple unique types which are
8721              based on the same origin type `T`
8722 
8723 Note: If a library routine cannot handle the Typedef type,
8724 you can use the `TypedefType` template to extract the
8725 type which the Typedef wraps.
8726  */
8727 struct Typedef(T, T init = T.init, string cookie=null)
8728 {
8729     private T Typedef_payload = init;
8730 
8731     // https://issues.dlang.org/show_bug.cgi?id=18415
8732     // prevent default construction if original type does too.
8733     static if ((is(T == struct) || is(T == union)) && !is(typeof({T t;})))
8734     {
8735         @disable this();
8736     }
8737 
8738     this(T init)
8739     {
8740         Typedef_payload = init;
8741     }
8742 
8743     this(Typedef tdef)
8744     {
8745         this(tdef.Typedef_payload);
8746     }
8747 
8748     // We need to add special overload for cast(Typedef!X) exp,
8749     // thus we can't simply inherit Proxy!Typedef_payload
8750     T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
8751     {
8752         return T2(cast(T) Typedef_payload);
8753     }
8754 
8755     auto ref opCast(T2, this X)()
8756     {
8757         return cast(T2) Typedef_payload;
8758     }
8759 
8760     mixin Proxy!Typedef_payload;
8761 
8762     pure nothrow @nogc @safe @property
8763     {
8764         alias TD = typeof(this);
8765         static if (isIntegral!T)
8766         {
8767             static TD min() {return TD(T.min);}
8768             static TD max() {return TD(T.max);}
8769         }
8770         else static if (isFloatingPoint!T)
8771         {
8772             static TD infinity() {return TD(T.infinity);}
8773             static TD nan() {return TD(T.nan);}
8774             static TD dig() {return TD(T.dig);}
8775             static TD epsilon() {return TD(T.epsilon);}
8776             static TD mant_dig() {return TD(T.mant_dig);}
8777             static TD max_10_exp() {return TD(T.max_10_exp);}
8778             static TD max_exp()  {return TD(T.max_exp);}
8779             static TD min_10_exp() {return TD(T.min_10_exp);}
8780             static TD min_exp() {return TD(T.min_exp);}
8781             static TD max() {return TD(T.max);}
8782             static TD min_normal() {return TD(T.min_normal);}
8783             TD re() {return TD(Typedef_payload.re);}
8784             TD im() {return TD(Typedef_payload.im);}
8785         }
8786     }
8787 
8788     /**
8789      * Convert wrapped value to a human readable string
8790      */
8791     string toString(this T)()
8792     {
8793         import std.array : appender;
8794         auto app = appender!string();
8795         auto spec = singleSpec("%s");
8796         toString(app, spec);
8797         return app.data;
8798     }
8799 
8800     /// ditto
8801     void toString(this T, W)(ref W writer, scope const ref FormatSpec!char fmt)
8802     if (isOutputRange!(W, char))
8803     {
8804         formatValue(writer, Typedef_payload, fmt);
8805     }
8806 
8807     ///
8808     @safe unittest
8809     {
8810         import std.conv : to;
8811 
8812         int i = 123;
8813         auto td = Typedef!int(i);
8814         assert(i.to!string == td.to!string);
8815     }
8816 }
8817 
8818 ///
8819 @safe unittest
8820 {
8821     alias MyInt = Typedef!int;
8822     MyInt foo = 10;
8823     foo++;
8824     assert(foo == 11);
8825 }
8826 
8827 /// custom initialization values
8828 @safe unittest
8829 {
8830     alias MyIntInit = Typedef!(int, 42);
8831     static assert(is(TypedefType!MyIntInit == int));
8832     static assert(MyIntInit() == 42);
8833 }
8834 
8835 /// Typedef creates a new type
8836 @safe unittest
8837 {
8838     alias MyInt = Typedef!int;
8839     static void takeInt(int) {}
8840     static void takeMyInt(MyInt) {}
8841 
8842     int i;
8843     takeInt(i);    // ok
8844     static assert(!__traits(compiles, takeMyInt(i)));
8845 
8846     MyInt myInt;
8847     static assert(!__traits(compiles, takeInt(myInt)));
8848     takeMyInt(myInt);  // ok
8849 }
8850 
8851 /// Use the optional `cookie` argument to create different types of the same base type
8852 @safe unittest
8853 {
8854     alias TypeInt1 = Typedef!int;
8855     alias TypeInt2 = Typedef!int;
8856 
8857     // The two Typedefs are the same type.
8858     static assert(is(TypeInt1 == TypeInt2));
8859 
8860     alias MoneyEuros = Typedef!(float, float.init, "euros");
8861     alias MoneyDollars = Typedef!(float, float.init, "dollars");
8862 
8863     // The two Typedefs are _not_ the same type.
8864     static assert(!is(MoneyEuros == MoneyDollars));
8865 }
8866 
8867 // https://issues.dlang.org/show_bug.cgi?id=12461
8868 @safe unittest
8869 {
8870     alias Int = Typedef!int;
8871 
8872     Int a, b;
8873     a += b;
8874     assert(a == 0);
8875 }
8876 
8877 /**
8878 Get the underlying type which a `Typedef` wraps.
8879 If `T` is not a `Typedef` it will alias itself to `T`.
8880 */
8881 template TypedefType(T)
8882 {
8883     static if (is(T : Typedef!Arg, Arg))
8884         alias TypedefType = Arg;
8885     else
8886         alias TypedefType = T;
8887 }
8888 
8889 ///
8890 @safe unittest
8891 {
8892     import std.conv : to;
8893 
8894     alias MyInt = Typedef!int;
8895     static assert(is(TypedefType!MyInt == int));
8896 
8897     /// Instantiating with a non-Typedef will return that type
8898     static assert(is(TypedefType!int == int));
8899 
8900     string num = "5";
8901 
8902     // extract the needed type
8903     MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
8904     assert(myInt == 5);
8905 
8906     // cast to the underlying type to get the value that's being wrapped
8907     int x = cast(TypedefType!MyInt) myInt;
8908 
8909     alias MyIntInit = Typedef!(int, 42);
8910     static assert(is(TypedefType!MyIntInit == int));
8911     static assert(MyIntInit() == 42);
8912 }
8913 
8914 @safe unittest
8915 {
8916     Typedef!int x = 10;
8917     static assert(!__traits(compiles, { int y = x; }));
8918     static assert(!__traits(compiles, { long z = x; }));
8919 
8920     Typedef!int y = 10;
8921     assert(x == y);
8922 
8923     static assert(Typedef!int.init == int.init);
8924 
8925     Typedef!(float, 1.0) z; // specifies the init
8926     assert(z == 1.0);
8927 
8928     static assert(typeof(z).init == 1.0);
8929 
8930     alias Dollar = Typedef!(int, 0, "dollar");
8931     alias Yen    = Typedef!(int, 0, "yen");
8932     static assert(!is(Dollar == Yen));
8933 
8934     Typedef!(int[3]) sa;
8935     static assert(sa.length == 3);
8936     static assert(typeof(sa).length == 3);
8937 
8938     Typedef!(int[3]) dollar1;
8939     assert(dollar1[0..$] is dollar1[0 .. 3]);
8940 
8941     Typedef!(int[]) dollar2;
8942     dollar2.length = 3;
8943     assert(dollar2[0..$] is dollar2[0 .. 3]);
8944 
8945     static struct Dollar1
8946     {
8947         static struct DollarToken {}
8948         enum opDollar = DollarToken.init;
8949         auto opSlice(size_t, DollarToken) { return 1; }
8950         auto opSlice(size_t, size_t) { return 2; }
8951     }
8952 
8953     Typedef!Dollar1 drange1;
8954     assert(drange1[0..$] == 1);
8955     assert(drange1[0 .. 1] == 2);
8956 
8957     static struct Dollar2
8958     {
8959         size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
8960         size_t opIndex(size_t i, size_t j) { return i + j; }
8961     }
8962 
8963     Typedef!Dollar2 drange2;
8964     assert(drange2[$, $] == 101);
8965 
8966     static struct Dollar3
8967     {
8968         size_t opDollar() { return 123; }
8969         size_t opIndex(size_t i) { return i; }
8970     }
8971 
8972     Typedef!Dollar3 drange3;
8973     assert(drange3[$] == 123);
8974 }
8975 
8976 // https://issues.dlang.org/show_bug.cgi?id=18415
8977 @safe @nogc pure nothrow unittest
8978 {
8979     struct NoDefCtorS{@disable this();}
8980     union NoDefCtorU{@disable this();}
8981     static assert(!is(typeof({Typedef!NoDefCtorS s;})));
8982     static assert(!is(typeof({Typedef!NoDefCtorU u;})));
8983 }
8984 
8985 // https://issues.dlang.org/show_bug.cgi?id=11703
8986 @safe @nogc pure nothrow unittest
8987 {
8988     alias I = Typedef!int;
8989     static assert(is(typeof(I.min) == I));
8990     static assert(is(typeof(I.max) == I));
8991 
8992     alias F = Typedef!double;
8993     static assert(is(typeof(F.infinity) == F));
8994     static assert(is(typeof(F.epsilon) == F));
8995 
8996     F f;
8997     assert(!is(typeof(F.re).stringof == double));
8998     assert(!is(typeof(F.im).stringof == double));
8999 }
9000 
9001 @safe unittest
9002 {
9003     // https://issues.dlang.org/show_bug.cgi?id=8655
9004     import std.typecons;
9005     import std.bitmanip;
9006     static import core.stdc.config;
9007 
9008     alias c_ulong = Typedef!(core.stdc.config.c_ulong);
9009 
9010     static struct Foo
9011     {
9012         mixin(bitfields!(
9013             c_ulong, "NameOffset", 31,
9014             c_ulong, "NameIsString", 1
9015         ));
9016     }
9017 }
9018 
9019 // https://issues.dlang.org/show_bug.cgi?id=12596
9020 @safe unittest
9021 {
9022     import std.typecons;
9023     alias TD = Typedef!int;
9024     TD x = TD(1);
9025     TD y = TD(x);
9026     assert(x == y);
9027 }
9028 
9029 @safe unittest // about toHash
9030 {
9031     import std.typecons;
9032     {
9033         alias TD = Typedef!int;
9034         int[TD] td;
9035         td[TD(1)] = 1;
9036         assert(td[TD(1)] == 1);
9037     }
9038 
9039     {
9040         alias TD = Typedef!(int[]);
9041         int[TD] td;
9042         td[TD([1,2,3,4])] = 2;
9043         assert(td[TD([1,2,3,4])] == 2);
9044     }
9045 
9046     {
9047         alias TD = Typedef!(int[][]);
9048         int[TD] td;
9049         td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
9050         assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
9051     }
9052 
9053     {
9054         struct MyStruct{ int x; }
9055         alias TD = Typedef!MyStruct;
9056         int[TD] td;
9057         td[TD(MyStruct(10))] = 4;
9058         assert(TD(MyStruct(20)) !in td);
9059         assert(td[TD(MyStruct(10))] == 4);
9060     }
9061 
9062     {
9063         static struct MyStruct2
9064         {
9065             int x;
9066             size_t toHash() const nothrow @safe { return x; }
9067             bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
9068         }
9069 
9070         alias TD = Typedef!MyStruct2;
9071         int[TD] td;
9072         td[TD(MyStruct2(50))] = 5;
9073         assert(td[TD(MyStruct2(50))] == 5);
9074     }
9075 
9076     {
9077         class MyClass{}
9078         alias TD = Typedef!MyClass;
9079         int[TD] td;
9080         auto c = new MyClass;
9081         td[TD(c)] = 6;
9082         assert(TD(new MyClass) !in td);
9083         assert(td[TD(c)] == 6);
9084     }
9085 }
9086 
9087 @system unittest
9088 {
9089     alias String = Typedef!(char[]);
9090     alias CString = Typedef!(const(char)[]);
9091     CString cs = "fubar";
9092     String s = cast(String) cs;
9093     assert(cs == s);
9094     char[] s2 = cast(char[]) cs;
9095     const(char)[] cs2 = cast(const(char)[])s;
9096     assert(s2 == cs2);
9097 }
9098 
9099 @system unittest // toString
9100 {
9101     import std.meta : AliasSeq;
9102     import std.conv : to;
9103 
9104     struct TestS {}
9105     class TestC {}
9106 
9107     static foreach (T; AliasSeq!(int, bool, float, double, real,
9108                                  char, dchar, wchar,
9109                                  TestS, TestC,
9110                                  int*, int[], int[2], int[int]))
9111     {{
9112         T t;
9113 
9114         Typedef!T td;
9115         Typedef!(const T) ctd;
9116         Typedef!(immutable T) itd;
9117 
9118         assert(t.to!string() == td.to!string());
9119 
9120         static if (!(is(T == TestS) || is(T == TestC)))
9121         {
9122             assert(t.to!string() == ctd.to!string());
9123             assert(t.to!string() == itd.to!string());
9124         }
9125     }}
9126 }
9127 
9128 @safe @nogc unittest // typedef'ed type with custom operators
9129 {
9130     static struct MyInt
9131     {
9132         int value;
9133         int opCmp(MyInt other)
9134         {
9135             if (value < other.value)
9136                 return -1;
9137             return !(value == other.value);
9138         }
9139     }
9140 
9141     auto m1 = Typedef!MyInt(MyInt(1));
9142     auto m2 = Typedef!MyInt(MyInt(2));
9143     assert(m1 < m2);
9144 }
9145 
9146 /**
9147 Allocates a `class` object right inside the current scope,
9148 therefore avoiding the overhead of `new`. This facility is unsafe;
9149 it is the responsibility of the user to not escape a reference to the
9150 object outside the scope.
9151 
9152 The class destructor will be called when the result of `scoped()` is
9153 itself destroyed.
9154 
9155 Scoped class instances can be embedded in a parent `class` or `struct`,
9156 just like a child struct instance. Scoped member variables must have
9157 type `typeof(scoped!Class(args))`, and be initialized with a call to
9158 scoped. See below for an example.
9159 
9160 Note:
9161 It's illegal to move a class instance even if you are sure there
9162 are no pointers to it. As such, it is illegal to move a scoped object.
9163  */
9164 template scoped(T)
9165 if (is(T == class))
9166 {
9167     // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
9168     // small objects). We will just use the maximum of filed alignments.
9169     enum alignment = __traits(classInstanceAlignment, T);
9170     alias aligned = _alignUp!alignment;
9171 
9172     static struct Scoped
9173     {
9174         // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
9175         private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
9176 
9177         @property inout(T) Scoped_payload() inout
9178         {
9179             void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
9180             // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
9181             immutable size_t d = alignedStore - Scoped_store.ptr;
9182             size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
9183             if (d != *currD)
9184             {
9185                 import core.stdc.string : memmove;
9186                 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
9187                 *currD = d;
9188             }
9189             return cast(inout(T)) alignedStore;
9190         }
9191         alias Scoped_payload this;
9192 
9193         @disable this();
9194         @disable this(this);
9195 
9196         ~this()
9197         {
9198             // `destroy` will also write .init but we have no functions in druntime
9199             // for deterministic finalization and memory releasing for now.
9200             .destroy(Scoped_payload);
9201         }
9202     }
9203 
9204     /** Returns the _scoped object.
9205     Params: args = Arguments to pass to `T`'s constructor.
9206     */
9207     @system auto scoped(Args...)(auto ref Args args)
9208     {
9209         import core.lifetime : emplace, forward;
9210 
9211         Scoped result = void;
9212         void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr);
9213         immutable size_t d = alignedStore - result.Scoped_store.ptr;
9214         *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
9215         emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], forward!args);
9216         return result;
9217     }
9218 }
9219 
9220 ///
9221 @system unittest
9222 {
9223     class A
9224     {
9225         int x;
9226         this()     {x = 0;}
9227         this(int i){x = i;}
9228         ~this()    {}
9229     }
9230 
9231     // Standard usage, constructing A on the stack
9232     auto a1 = scoped!A();
9233     a1.x = 42;
9234 
9235     // Result of `scoped` call implicitly converts to a class reference
9236     A aRef = a1;
9237     assert(aRef.x == 42);
9238 
9239     // Scoped destruction
9240     {
9241         auto a2 = scoped!A(1);
9242         assert(a2.x == 1);
9243         aRef = a2;
9244         // a2 is destroyed here, calling A's destructor
9245     }
9246     // aRef is now an invalid reference
9247 
9248     // Here the temporary scoped A is immediately destroyed.
9249     // This means the reference is then invalid.
9250     version (Bug)
9251     {
9252         // Wrong, should use `auto`
9253         A invalid = scoped!A();
9254     }
9255 
9256     // Restrictions
9257     version (Bug)
9258     {
9259         import std.algorithm.mutation : move;
9260         auto invalid = a1.move; // illegal, scoped objects can't be moved
9261     }
9262     static assert(!is(typeof({
9263         auto e1 = a1; // illegal, scoped objects can't be copied
9264         assert([a1][0].x == 42); // ditto
9265     })));
9266     static assert(!is(typeof({
9267         alias ScopedObject = typeof(a1);
9268         auto e2 = ScopedObject();  // illegal, must be built via scoped!A
9269         auto e3 = ScopedObject(1); // ditto
9270     })));
9271 
9272     // Use with alias
9273     alias makeScopedA = scoped!A;
9274     auto a3 = makeScopedA();
9275     auto a4 = makeScopedA(1);
9276 
9277     // Use as member variable
9278     struct B
9279     {
9280         typeof(scoped!A()) a; // note the trailing parentheses
9281 
9282         this(int i)
9283         {
9284             // construct member
9285             a = scoped!A(i);
9286         }
9287     }
9288 
9289     // Stack-allocate
9290     auto b1 = B(5);
9291     aRef = b1.a;
9292     assert(aRef.x == 5);
9293     destroy(b1); // calls A's destructor for b1.a
9294     // aRef is now an invalid reference
9295 
9296     // Heap-allocate
9297     auto b2 = new B(6);
9298     assert(b2.a.x == 6);
9299     destroy(*b2); // calls A's destructor for b2.a
9300 }
9301 
9302 private size_t _alignUp(size_t alignment)(size_t n)
9303 if (alignment > 0 && !((alignment - 1) & alignment))
9304 {
9305     enum badEnd = alignment - 1; // 0b11, 0b111, ...
9306     return (n + badEnd) & ~badEnd;
9307 }
9308 
9309 // https://issues.dlang.org/show_bug.cgi?id=6580 testcase
9310 @system unittest
9311 {
9312     enum alignment = (void*).alignof;
9313 
9314     static class C0 { }
9315     static class C1 { byte b; }
9316     static class C2 { byte[2] b; }
9317     static class C3 { byte[3] b; }
9318     static class C7 { byte[7] b; }
9319     static assert(scoped!C0().sizeof % alignment == 0);
9320     static assert(scoped!C1().sizeof % alignment == 0);
9321     static assert(scoped!C2().sizeof % alignment == 0);
9322     static assert(scoped!C3().sizeof % alignment == 0);
9323     static assert(scoped!C7().sizeof % alignment == 0);
9324 
9325     enum longAlignment = long.alignof;
9326     static class C1long
9327     {
9328         long long_; byte byte_ = 4;
9329         this() { }
9330         this(long _long, ref int i) { long_ = _long; ++i; }
9331     }
9332     static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
9333     static assert(scoped!C1long().sizeof % longAlignment == 0);
9334     static assert(scoped!C2long().sizeof % longAlignment == 0);
9335 
9336     void alignmentTest()
9337     {
9338         int var = 5;
9339         auto c1long = scoped!C1long(3, var);
9340         assert(var == 6);
9341         auto c2long = scoped!C2long();
9342         assert(cast(uint)&c1long.long_ % longAlignment == 0);
9343         assert(cast(uint)&c2long.long_ % longAlignment == 0);
9344         assert(c1long.long_ == 3 && c1long.byte_ == 4);
9345         assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
9346     }
9347 
9348     alignmentTest();
9349 
9350     version (DigitalMars)
9351     {
9352         void test(size_t size)
9353         {
9354             import core.stdc.stdlib : alloca;
9355             cast(void) alloca(size);
9356             alignmentTest();
9357         }
9358         foreach (i; 0 .. 10)
9359             test(i);
9360     }
9361     else
9362     {
9363         void test(size_t size)()
9364         {
9365             byte[size] arr;
9366             alignmentTest();
9367         }
9368         static foreach (i; 0 .. 11)
9369             test!i();
9370     }
9371 }
9372 
9373 // Original https://issues.dlang.org/show_bug.cgi?id=6580 testcase
9374 @system unittest
9375 {
9376     class C { int i; byte b; }
9377 
9378     auto sa = [scoped!C(), scoped!C()];
9379     assert(cast(uint)&sa[0].i % int.alignof == 0);
9380     assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
9381 }
9382 
9383 @system unittest
9384 {
9385     class A { int x = 1; }
9386     auto a1 = scoped!A();
9387     assert(a1.x == 1);
9388     auto a2 = scoped!A();
9389     a1.x = 42;
9390     a2.x = 53;
9391     assert(a1.x == 42);
9392 }
9393 
9394 @system unittest
9395 {
9396     class A { int x = 1; this() { x = 2; } }
9397     auto a1 = scoped!A();
9398     assert(a1.x == 2);
9399     auto a2 = scoped!A();
9400     a1.x = 42;
9401     a2.x = 53;
9402     assert(a1.x == 42);
9403 }
9404 
9405 @system unittest
9406 {
9407     class A { int x = 1; this(int y) { x = y; } ~this() {} }
9408     auto a1 = scoped!A(5);
9409     assert(a1.x == 5);
9410     auto a2 = scoped!A(42);
9411     a1.x = 42;
9412     a2.x = 53;
9413     assert(a1.x == 42);
9414 }
9415 
9416 @system unittest
9417 {
9418     class A { static bool dead; ~this() { dead = true; } }
9419     class B : A { static bool dead; ~this() { dead = true; } }
9420     {
9421         auto b = scoped!B();
9422     }
9423     assert(B.dead, "asdasd");
9424     assert(A.dead, "asdasd");
9425 }
9426 
9427 // https://issues.dlang.org/show_bug.cgi?id=8039 testcase
9428 @system unittest
9429 {
9430     static int dels;
9431     static struct S { ~this(){ ++dels; } }
9432 
9433     static class A { S s; }
9434     dels = 0; { scoped!A(); }
9435     assert(dels == 1);
9436 
9437     static class B { S[2] s; }
9438     dels = 0; { scoped!B(); }
9439     assert(dels == 2);
9440 
9441     static struct S2 { S[3] s; }
9442     static class C { S2[2] s; }
9443     dels = 0; { scoped!C(); }
9444     assert(dels == 6);
9445 
9446     static class D: A { S2[2] s; }
9447     dels = 0; { scoped!D(); }
9448     assert(dels == 1+6);
9449 }
9450 
9451 @system unittest
9452 {
9453     // https://issues.dlang.org/show_bug.cgi?id=4500
9454     class A
9455     {
9456         this() { a = this; }
9457         this(int i) { a = this; }
9458         A a;
9459         bool check() { return this is a; }
9460     }
9461 
9462     auto a1 = scoped!A();
9463     assert(a1.check());
9464 
9465     auto a2 = scoped!A(1);
9466     assert(a2.check());
9467 
9468     a1.a = a1;
9469     assert(a1.check());
9470 }
9471 
9472 @system unittest
9473 {
9474     static class A
9475     {
9476         static int sdtor;
9477 
9478         this() { ++sdtor; assert(sdtor == 1); }
9479         ~this() { assert(sdtor == 1); --sdtor; }
9480     }
9481 
9482     interface Bob {}
9483 
9484     static class ABob : A, Bob
9485     {
9486         this() { ++sdtor; assert(sdtor == 2); }
9487         ~this() { assert(sdtor == 2); --sdtor; }
9488     }
9489 
9490     A.sdtor = 0;
9491     scope(exit) assert(A.sdtor == 0);
9492     auto abob = scoped!ABob();
9493 }
9494 
9495 @safe unittest
9496 {
9497     static class A { this(int) {} }
9498     static assert(!__traits(compiles, scoped!A()));
9499 }
9500 
9501 @system unittest
9502 {
9503     static class A { @property inout(int) foo() inout { return 1; } }
9504 
9505     auto a1 = scoped!A();
9506     assert(a1.foo == 1);
9507     static assert(is(typeof(a1.foo) == int));
9508 
9509     auto a2 = scoped!(const(A))();
9510     assert(a2.foo == 1);
9511     static assert(is(typeof(a2.foo) == const(int)));
9512 
9513     auto a3 = scoped!(immutable(A))();
9514     assert(a3.foo == 1);
9515     static assert(is(typeof(a3.foo) == immutable(int)));
9516 
9517     const c1 = scoped!A();
9518     assert(c1.foo == 1);
9519     static assert(is(typeof(c1.foo) == const(int)));
9520 
9521     const c2 = scoped!(const(A))();
9522     assert(c2.foo == 1);
9523     static assert(is(typeof(c2.foo) == const(int)));
9524 
9525     const c3 = scoped!(immutable(A))();
9526     assert(c3.foo == 1);
9527     static assert(is(typeof(c3.foo) == immutable(int)));
9528 }
9529 
9530 @system unittest
9531 {
9532     class C
9533     {
9534         this(int rval) { assert(rval == 1); }
9535         this(ref int lval) { assert(lval == 3); ++lval; }
9536     }
9537 
9538     auto c1 = scoped!C(1);
9539     int lval = 3;
9540     auto c2 = scoped!C(lval);
9541     assert(lval == 4);
9542 }
9543 
9544 @system unittest
9545 {
9546     class C
9547     {
9548         this(){}
9549         this(int){}
9550         this(int, int){}
9551     }
9552     alias makeScopedC = scoped!C;
9553 
9554     auto a = makeScopedC();
9555     auto b = makeScopedC(1);
9556     auto c = makeScopedC(1, 1);
9557 
9558     static assert(is(typeof(a) == typeof(b)));
9559     static assert(is(typeof(b) == typeof(c)));
9560 }
9561 
9562 /**
9563 Defines a simple, self-documenting yes/no flag. This makes it easy for
9564 APIs to define functions accepting flags without resorting to $(D
9565 bool), which is opaque in calls, and without needing to define an
9566 enumerated type separately. Using `Flag!"Name"` instead of $(D
9567 bool) makes the flag's meaning visible in calls. Each yes/no flag has
9568 its own type, which makes confusions and mix-ups impossible.
9569 
9570 Example:
9571 
9572 Code calling `getLine` (usually far away from its definition) can't be
9573 understood without looking at the documentation, even by users familiar with
9574 the API:
9575 ----
9576 string getLine(bool keepTerminator)
9577 {
9578     ...
9579     if (keepTerminator) ...
9580     ...
9581 }
9582 ...
9583 auto line = getLine(false);
9584 ----
9585 
9586 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
9587 code compiles and runs with erroneous results.
9588 
9589 After replacing the boolean parameter with an instantiation of `Flag`, code
9590 calling `getLine` can be easily read and understood even by people not
9591 fluent with the API:
9592 
9593 ----
9594 string getLine(Flag!"keepTerminator" keepTerminator)
9595 {
9596     ...
9597     if (keepTerminator) ...
9598     ...
9599 }
9600 ...
9601 auto line = getLine(Yes.keepTerminator);
9602 ----
9603 
9604 The structs `Yes` and `No` are provided as shorthand for
9605 `Flag!"Name".yes` and `Flag!"Name".no` and are preferred for brevity and
9606 readability. These convenience structs mean it is usually unnecessary and
9607 counterproductive to create an alias of a `Flag` as a way of avoiding typing
9608 out the full type while specifying the affirmative or negative options.
9609 
9610 Passing categorical data by means of unstructured `bool`
9611 parameters is classified under "simple-data coupling" by Steve
9612 McConnell in the $(LUCKY Code Complete) book, along with three other
9613 kinds of coupling. The author argues citing several studies that
9614 coupling has a negative effect on code quality. `Flag` offers a
9615 simple structuring method for passing yes/no flags to APIs.
9616  */
9617 template Flag(string name) {
9618     ///
9619     enum Flag : bool
9620     {
9621         /**
9622          When creating a value of type `Flag!"Name"`, use $(D
9623          Flag!"Name".no) for the negative option. When using a value
9624          of type `Flag!"Name"`, compare it against $(D
9625          Flag!"Name".no) or just `false` or `0`.  */
9626         no = false,
9627 
9628         /** When creating a value of type `Flag!"Name"`, use $(D
9629          Flag!"Name".yes) for the affirmative option. When using a
9630          value of type `Flag!"Name"`, compare it against $(D
9631          Flag!"Name".yes).
9632         */
9633         yes = true
9634     }
9635 }
9636 
9637 ///
9638 @safe unittest
9639 {
9640     Flag!"abc" flag;
9641 
9642     assert(flag == Flag!"abc".no);
9643     assert(flag == No.abc);
9644     assert(!flag);
9645     if (flag) assert(0);
9646 }
9647 
9648 ///
9649 @safe unittest
9650 {
9651     auto flag = Yes.abc;
9652 
9653     assert(flag);
9654     assert(flag == Yes.abc);
9655     if (!flag) assert(0);
9656     if (flag) {} else assert(0);
9657 }
9658 
9659 /**
9660 Convenience names that allow using e.g. `Yes.encryption` instead of
9661 `Flag!"encryption".yes` and `No.encryption` instead of $(D
9662 Flag!"encryption".no).
9663 */
9664 struct Yes
9665 {
9666     template opDispatch(string name)
9667     {
9668         enum opDispatch = Flag!name.yes;
9669     }
9670 }
9671 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
9672 
9673 /// Ditto
9674 struct No
9675 {
9676     template opDispatch(string name)
9677     {
9678         enum opDispatch = Flag!name.no;
9679     }
9680 }
9681 
9682 ///
9683 @safe unittest
9684 {
9685     Flag!"abc" flag;
9686 
9687     assert(flag == Flag!"abc".no);
9688     assert(flag == No.abc);
9689     assert(!flag);
9690     if (flag) assert(0);
9691 }
9692 
9693 ///
9694 @safe unittest
9695 {
9696     auto flag = Yes.abc;
9697 
9698     assert(flag);
9699     assert(flag == Yes.abc);
9700     if (!flag) assert(0);
9701     if (flag) {} else assert(0);
9702 }
9703 
9704 /**
9705 Detect whether an enum is of integral type and has only "flag" values
9706 (i.e. values with a bit count of exactly 1).
9707 Additionally, a zero value is allowed for compatibility with enums including
9708 a "None" value.
9709 */
9710 template isBitFlagEnum(E)
9711 {
9712     static if (is(E Base == enum) && isIntegral!Base)
9713     {
9714         enum isBitFlagEnum = (E.min >= 0) &&
9715         {
9716             static foreach (immutable flag; EnumMembers!E)
9717             {{
9718                 Base value = flag;
9719                 value &= value - 1;
9720                 if (value != 0) return false;
9721             }}
9722             return true;
9723         }();
9724     }
9725     else
9726     {
9727         enum isBitFlagEnum = false;
9728     }
9729 }
9730 
9731 ///
9732 @safe pure nothrow unittest
9733 {
9734     enum A
9735     {
9736         None,
9737         A = 1 << 0,
9738         B = 1 << 1,
9739         C = 1 << 2,
9740         D = 1 << 3,
9741     }
9742 
9743     static assert(isBitFlagEnum!A);
9744 }
9745 
9746 /// Test an enum with default (consecutive) values
9747 @safe pure nothrow unittest
9748 {
9749     enum B
9750     {
9751         A,
9752         B,
9753         C,
9754         D // D == 3
9755     }
9756 
9757     static assert(!isBitFlagEnum!B);
9758 }
9759 
9760 /// Test an enum with non-integral values
9761 @safe pure nothrow unittest
9762 {
9763     enum C: double
9764     {
9765         A = 1 << 0,
9766         B = 1 << 1
9767     }
9768 
9769     static assert(!isBitFlagEnum!C);
9770 }
9771 
9772 /**
9773 A typesafe structure for storing combinations of enum values.
9774 
9775 This template defines a simple struct to represent bitwise OR combinations of
9776 enum values. It can be used if all the enum values are integral constants with
9777 a bit count of at most 1, or if the `unsafe` parameter is explicitly set to
9778 Yes.
9779 This is much safer than using the enum itself to store
9780 the OR combination, which can produce surprising effects like this:
9781 ----
9782 enum E
9783 {
9784     A = 1 << 0,
9785     B = 1 << 1
9786 }
9787 E e = E.A | E.B;
9788 // will throw SwitchError
9789 final switch (e)
9790 {
9791     case E.A:
9792         return;
9793     case E.B:
9794         return;
9795 }
9796 ----
9797 */
9798 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe)
9799 if (unsafe || isBitFlagEnum!(E))
9800 {
9801 @safe @nogc pure nothrow:
9802 private:
9803     enum isBaseEnumType(T) = is(E == T);
9804     alias Base = OriginalType!E;
9805     Base mValue;
9806 
9807 public:
9808     this(E flag)
9809     {
9810         this = flag;
9811     }
9812 
9813     this(T...)(T flags)
9814         if (allSatisfy!(isBaseEnumType, T))
9815     {
9816         this = flags;
9817     }
9818 
9819     bool opCast(B: bool)() const
9820     {
9821         return mValue != 0;
9822     }
9823 
9824     Base opCast(B)() const
9825         if (is(Base : B))
9826     {
9827         return mValue;
9828     }
9829 
9830     auto opUnary(string op)() const
9831         if (op == "~")
9832     {
9833         return BitFlags(cast(E) cast(Base) ~mValue);
9834     }
9835 
9836     auto ref opAssign(T...)(T flags)
9837         if (allSatisfy!(isBaseEnumType, T))
9838     {
9839         mValue = 0;
9840         foreach (E flag; flags)
9841         {
9842             mValue |= flag;
9843         }
9844         return this;
9845     }
9846 
9847     auto ref opAssign(E flag)
9848     {
9849         mValue = flag;
9850         return this;
9851     }
9852 
9853     auto ref opOpAssign(string op: "|")(BitFlags flags)
9854     {
9855         mValue |= flags.mValue;
9856         return this;
9857     }
9858 
9859     auto ref opOpAssign(string op: "&")(BitFlags  flags)
9860     {
9861         mValue &= flags.mValue;
9862         return this;
9863     }
9864 
9865     auto ref opOpAssign(string op: "|")(E flag)
9866     {
9867         mValue |= flag;
9868         return this;
9869     }
9870 
9871     auto ref opOpAssign(string op: "&")(E flag)
9872     {
9873         mValue &= flag;
9874         return this;
9875     }
9876 
9877     auto opBinary(string op)(BitFlags flags) const
9878         if (op == "|" || op == "&")
9879     {
9880         BitFlags result = this;
9881         result.opOpAssign!op(flags);
9882         return result;
9883     }
9884 
9885     auto opBinary(string op)(E flag) const
9886         if (op == "|" || op == "&")
9887     {
9888         BitFlags result = this;
9889         result.opOpAssign!op(flag);
9890         return result;
9891     }
9892 
9893     auto opBinaryRight(string op)(E flag) const
9894         if (op == "|" || op == "&")
9895     {
9896         return opBinary!op(flag);
9897     }
9898 
9899     bool opDispatch(string name)() const
9900     if (__traits(hasMember, E, name))
9901     {
9902         enum e = __traits(getMember, E, name);
9903         return (mValue & e) == e;
9904     }
9905 
9906     void opDispatch(string name)(bool set)
9907     if (__traits(hasMember, E, name))
9908     {
9909         enum e = __traits(getMember, E, name);
9910         if (set)
9911             mValue |= e;
9912         else
9913             mValue &= ~e;
9914     }
9915 }
9916 
9917 /// Set values with the | operator and test with &
9918 @safe @nogc pure nothrow unittest
9919 {
9920     enum Enum
9921     {
9922         A = 1 << 0,
9923     }
9924 
9925     // A default constructed BitFlags has no value set
9926     immutable BitFlags!Enum flags_empty;
9927     assert(!flags_empty.A);
9928 
9929     // Value can be set with the | operator
9930     immutable flags_A = flags_empty | Enum.A;
9931 
9932     // and tested using property access
9933     assert(flags_A.A);
9934 
9935     // or the & operator
9936     assert(flags_A & Enum.A);
9937     // which commutes.
9938     assert(Enum.A & flags_A);
9939 }
9940 
9941 /// A default constructed BitFlags has no value set
9942 @safe @nogc pure nothrow unittest
9943 {
9944     enum Enum
9945     {
9946         None,
9947         A = 1 << 0,
9948         B = 1 << 1,
9949         C = 1 << 2
9950     }
9951 
9952     immutable BitFlags!Enum flags_empty;
9953     assert(!(flags_empty & (Enum.A | Enum.B | Enum.C)));
9954     assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
9955 }
9956 
9957 // BitFlags can be variadically initialized
9958 @safe @nogc pure nothrow unittest
9959 {
9960     import std.traits : EnumMembers;
9961 
9962     enum Enum
9963     {
9964         A = 1 << 0,
9965         B = 1 << 1,
9966         C = 1 << 2
9967     }
9968 
9969     // Values can also be set using property access
9970     BitFlags!Enum flags;
9971     flags.A = true;
9972     assert(flags & Enum.A);
9973     flags.A = false;
9974     assert(!(flags & Enum.A));
9975 
9976     // BitFlags can be variadically initialized
9977     immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9978     assert(flags_AB.A && flags_AB.B && !flags_AB.C);
9979 
9980     // You can use the EnumMembers template to set all flags
9981     immutable BitFlags!Enum flags_all = EnumMembers!Enum;
9982     assert(flags_all.A && flags_all.B && flags_all.C);
9983 }
9984 
9985 /// Binary operations: subtracting and intersecting flags
9986 @safe @nogc pure nothrow unittest
9987 {
9988     enum Enum
9989     {
9990         A = 1 << 0,
9991         B = 1 << 1,
9992         C = 1 << 2,
9993     }
9994     immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9995     immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
9996 
9997     // Use the ~ operator for subtracting flags
9998     immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
9999     assert(!flags_B.A && flags_B.B && !flags_B.C);
10000 
10001     // use & between BitFlags for intersection
10002     assert(flags_B == (flags_BC & flags_AB));
10003 }
10004 
10005 /// All the binary operators work in their assignment version
10006 @safe @nogc pure nothrow unittest
10007 {
10008     enum Enum
10009     {
10010         A = 1 << 0,
10011         B = 1 << 1,
10012     }
10013 
10014     BitFlags!Enum flags_empty, temp, flags_AB;
10015     flags_AB = Enum.A | Enum.B;
10016 
10017     temp |= flags_AB;
10018     assert(temp == (flags_empty | flags_AB));
10019 
10020     temp = flags_empty;
10021     temp |= Enum.B;
10022     assert(temp == (flags_empty | Enum.B));
10023 
10024     temp = flags_empty;
10025     temp &= flags_AB;
10026     assert(temp == (flags_empty & flags_AB));
10027 
10028     temp = flags_empty;
10029     temp &= Enum.A;
10030     assert(temp == (flags_empty & Enum.A));
10031 }
10032 
10033 /// Conversion to bool and int
10034 @safe @nogc pure nothrow unittest
10035 {
10036     enum Enum
10037     {
10038         A = 1 << 0,
10039         B = 1 << 1,
10040     }
10041 
10042     BitFlags!Enum flags;
10043 
10044     // BitFlags with no value set evaluate to false
10045     assert(!flags);
10046 
10047     // BitFlags with at least one value set evaluate to true
10048     flags |= Enum.A;
10049     assert(flags);
10050 
10051     // This can be useful to check intersection between BitFlags
10052     BitFlags!Enum flags_AB = Enum.A | Enum.B;
10053     assert(flags & flags_AB);
10054     assert(flags & Enum.A);
10055 
10056     // You can of course get you raw value out of flags
10057     auto value = cast(int) flags;
10058     assert(value == Enum.A);
10059 }
10060 
10061 /// You need to specify the `unsafe` parameter for enums with custom values
10062 @safe @nogc pure nothrow unittest
10063 {
10064     enum UnsafeEnum
10065     {
10066         A = 1,
10067         B = 2,
10068         C = 4,
10069         BC = B|C
10070     }
10071     static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags; }));
10072     BitFlags!(UnsafeEnum, Yes.unsafe) flags;
10073 
10074     // property access tests for exact match of unsafe enums
10075     flags.B = true;
10076     assert(!flags.BC); // only B
10077     flags.C = true;
10078     assert(flags.BC); // both B and C
10079     flags.B = false;
10080     assert(!flags.BC); // only C
10081 
10082     // property access sets all bits of unsafe enum group
10083     flags = flags.init;
10084     flags.BC = true;
10085     assert(!flags.A && flags.B && flags.C);
10086     flags.A = true;
10087     flags.BC = false;
10088     assert(flags.A && !flags.B && !flags.C);
10089 }
10090 
10091 // Negation of BitFlags should work with any base type.
10092 // Double-negation of BitFlags should work.
10093 @safe @nogc pure nothrow unittest
10094 {
10095     static foreach (alias Base; AliasSeq!(
10096         byte,
10097         ubyte,
10098         short,
10099         ushort,
10100         int,
10101         uint,
10102         long,
10103         ulong,
10104     ))
10105     {{
10106         enum Enum : Base
10107         {
10108             A = 1 << 0,
10109             B = 1 << 1,
10110             C = 1 << 2,
10111         }
10112 
10113         auto flags = BitFlags!Enum(Enum.A);
10114 
10115         assert(flags == ~~flags);
10116     }}
10117 }
10118 
10119 private enum false_(T) = false;
10120 
10121 // ReplaceType
10122 /**
10123 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
10124 example, `ReplaceType!(int, uint, Tuple!(int, float)[string])` yields
10125 `Tuple!(uint, float)[string]`. The types in which replacement is performed
10126 may be arbitrarily complex, including qualifiers, built-in type constructors
10127 (pointers, arrays, associative arrays, functions, and delegates), and template
10128 instantiations; replacement proceeds transitively through the type definition.
10129 However, member types in `struct`s or `class`es are not replaced because there
10130 are no ways to express the types resulting after replacement.
10131 
10132 This is an advanced type manipulation necessary e.g. for replacing the
10133 placeholder type `This` in $(REF Algebraic, std,variant).
10134 
10135 Returns: `ReplaceType` aliases itself to the type(s) that result after
10136 replacement.
10137 */
10138 alias ReplaceType(From, To, T...) = ReplaceTypeUnless!(false_, From, To, T);
10139 
10140 ///
10141 @safe unittest
10142 {
10143     static assert(
10144         is(ReplaceType!(int, string, int[]) == string[]) &&
10145         is(ReplaceType!(int, string, int[int]) == string[string]) &&
10146         is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
10147         is(ReplaceType!(int, string, Tuple!(int[], float))
10148             == Tuple!(string[], float))
10149     );
10150 }
10151 
10152 /**
10153 Like $(LREF ReplaceType), but does not perform replacement in types for which
10154 `pred` evaluates to `true`.
10155 */
10156 template ReplaceTypeUnless(alias pred, From, To, T...)
10157 {
10158     import std.meta;
10159 
10160     static if (T.length == 1)
10161     {
10162         static if (pred!(T[0]))
10163             alias ReplaceTypeUnless = T[0];
10164         else static if (is(T[0] == From))
10165             alias ReplaceTypeUnless = To;
10166         else static if (is(T[0] == const(U), U))
10167             alias ReplaceTypeUnless = const(ReplaceTypeUnless!(pred, From, To, U));
10168         else static if (is(T[0] == immutable(U), U))
10169             alias ReplaceTypeUnless = immutable(ReplaceTypeUnless!(pred, From, To, U));
10170         else static if (is(T[0] == shared(U), U))
10171             alias ReplaceTypeUnless = shared(ReplaceTypeUnless!(pred, From, To, U));
10172         else static if (is(T[0] == U*, U))
10173         {
10174             static if (is(U == function))
10175                 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
10176             else
10177                 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)*;
10178         }
10179         else static if (is(T[0] == delegate))
10180         {
10181             alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
10182         }
10183         else static if (is(T[0] == function))
10184         {
10185             static assert(0, "Function types not supported," ~
10186                 " use a function pointer type instead of " ~ T[0].stringof);
10187         }
10188         else static if (is(T[0] == U!V, alias U, V...))
10189         {
10190             template replaceTemplateArgs(T...)
10191             {
10192                 static if (is(typeof(T[0]))) {   // template argument is value or symbol
10193                     static if (__traits(compiles, { alias _ = T[0]; }))
10194                         // it's a symbol
10195                         alias replaceTemplateArgs = T[0];
10196                     else
10197                         // it's a value
10198                         enum replaceTemplateArgs = T[0];
10199                 } else
10200                     alias replaceTemplateArgs = ReplaceTypeUnless!(pred, From, To, T[0]);
10201             }
10202             alias ReplaceTypeUnless = U!(staticMap!(replaceTemplateArgs, V));
10203         }
10204         else static if (is(T[0] == struct))
10205             // don't match with alias this struct below
10206             // https://issues.dlang.org/show_bug.cgi?id=15168
10207             alias ReplaceTypeUnless = T[0];
10208         else static if (is(T[0] == U[], U))
10209             alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[];
10210         else static if (is(T[0] == U[n], U, size_t n))
10211             alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[n];
10212         else static if (is(T[0] == U[V], U, V))
10213             alias ReplaceTypeUnless =
10214                 ReplaceTypeUnless!(pred, From, To, U)[ReplaceTypeUnless!(pred, From, To, V)];
10215         else
10216             alias ReplaceTypeUnless = T[0];
10217     }
10218     else static if (T.length > 1)
10219     {
10220         alias ReplaceTypeUnless = AliasSeq!(ReplaceTypeUnless!(pred, From, To, T[0]),
10221             ReplaceTypeUnless!(pred, From, To, T[1 .. $]));
10222     }
10223     else
10224     {
10225         alias ReplaceTypeUnless = AliasSeq!();
10226     }
10227 }
10228 
10229 ///
10230 @safe unittest
10231 {
10232     import std.traits : isArray;
10233 
10234     static assert(
10235         is(ReplaceTypeUnless!(isArray, int, string, int*) == string*) &&
10236         is(ReplaceTypeUnless!(isArray, int, string, int[]) == int[]) &&
10237         is(ReplaceTypeUnless!(isArray, int, string, Tuple!(int, int[]))
10238             == Tuple!(string, int[]))
10239    );
10240 }
10241 
10242 private template replaceTypeInFunctionTypeUnless(alias pred, From, To, fun)
10243 {
10244     alias RX = ReplaceTypeUnless!(pred, From, To, ReturnType!fun);
10245     alias PX = AliasSeq!(ReplaceTypeUnless!(pred, From, To, Parameters!fun));
10246     // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
10247     // tuple if Parameters!fun.length == 1
10248 
10249     string gen()
10250     {
10251         enum  linkage = functionLinkage!fun;
10252         alias attributes = functionAttributes!fun;
10253         enum  variadicStyle = variadicFunctionStyle!fun;
10254         alias storageClasses = ParameterStorageClassTuple!fun;
10255 
10256         string result;
10257 
10258         result ~= "extern(" ~ linkage ~ ") ";
10259         static if (attributes & FunctionAttribute.ref_)
10260         {
10261             result ~= "ref ";
10262         }
10263 
10264         result ~= "RX";
10265         static if (is(fun == delegate))
10266             result ~= " delegate";
10267         else
10268             result ~= " function";
10269 
10270         result ~= "(";
10271         static foreach (i; 0 .. PX.length)
10272         {
10273             if (i)
10274                 result ~= ", ";
10275             if (storageClasses[i] & ParameterStorageClass.scope_)
10276                 result ~= "scope ";
10277             if (storageClasses[i] & ParameterStorageClass.in_)
10278                 result ~= "in ";
10279             if (storageClasses[i] & ParameterStorageClass.out_)
10280                 result ~= "out ";
10281             if (storageClasses[i] & ParameterStorageClass.ref_)
10282                 result ~= "ref ";
10283             if (storageClasses[i] & ParameterStorageClass.lazy_)
10284                 result ~= "lazy ";
10285             if (storageClasses[i] & ParameterStorageClass.return_)
10286                 result ~= "return ";
10287 
10288             result ~= "PX[" ~ i.stringof ~ "]";
10289         }
10290         static if (variadicStyle == Variadic.typesafe)
10291             result ~= " ...";
10292         else static if (variadicStyle != Variadic.no)
10293             result ~= ", ...";
10294         result ~= ")";
10295 
10296         static if (attributes & FunctionAttribute.pure_)
10297             result ~= " pure";
10298         static if (attributes & FunctionAttribute.nothrow_)
10299             result ~= " nothrow";
10300         static if (attributes & FunctionAttribute.property)
10301             result ~= " @property";
10302         static if (attributes & FunctionAttribute.trusted)
10303             result ~= " @trusted";
10304         static if (attributes & FunctionAttribute.safe)
10305             result ~= " @safe";
10306         static if (attributes & FunctionAttribute.nogc)
10307             result ~= " @nogc";
10308         static if (attributes & FunctionAttribute.system)
10309             result ~= " @system";
10310         static if (attributes & FunctionAttribute.const_)
10311             result ~= " const";
10312         static if (attributes & FunctionAttribute.immutable_)
10313             result ~= " immutable";
10314         static if (attributes & FunctionAttribute.inout_)
10315             result ~= " inout";
10316         static if (attributes & FunctionAttribute.shared_)
10317             result ~= " shared";
10318         static if (attributes & FunctionAttribute.return_)
10319             result ~= " return";
10320         static if (attributes & FunctionAttribute.live)
10321             result ~= " @live";
10322 
10323         return result;
10324     }
10325 
10326     mixin("alias replaceTypeInFunctionTypeUnless = " ~ gen() ~ ";");
10327 }
10328 
10329 @safe unittest
10330 {
10331     template Test(Ts...)
10332     {
10333         static if (Ts.length)
10334         {
10335             //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
10336             //    ~Ts[1].stringof~", "~Ts[2].stringof~")");
10337             static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
10338                 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
10339                     ~Ts[2].stringof~") == "
10340                     ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
10341             alias Test = Test!(Ts[4 .. $]);
10342         }
10343         else alias Test = void;
10344     }
10345 
10346     //import core.stdc.stdio;
10347     alias RefFun1 = ref int function(float, long);
10348     alias RefFun2 = ref float function(float, long);
10349     extern(C) int printf(const char*, ...) nothrow @nogc @system;
10350     extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
10351     int func(float);
10352 
10353     int x;
10354     struct S1 { void foo() { x = 1; } }
10355     struct S2 { void bar() { x = 2; } }
10356 
10357     alias Pass = Test!(
10358         int, float, typeof(&func), float delegate(float),
10359         int, float, typeof(&printf), typeof(&floatPrintf),
10360         int, float, int function(out long, ...),
10361             float function(out long, ...),
10362         int, float, int function(ref float, long),
10363             float function(ref float, long),
10364         int, float, int function(ref int, long),
10365             float function(ref float, long),
10366         int, float, int function(out int, long),
10367             float function(out float, long),
10368         int, float, int function(lazy int, long),
10369             float function(lazy float, long),
10370         int, float, int function(out long, ref const int),
10371             float function(out long, ref const float),
10372         int, float, int function(in long, ref const int),
10373             float function(in long, ref const float),
10374         int, float, int function(long, in int),
10375             float function(long, in float),
10376         int, int, int, int,
10377         int, float, int, float,
10378         int, float, const int, const float,
10379         int, float, immutable int, immutable float,
10380         int, float, shared int, shared float,
10381         int, float, int*, float*,
10382         int, float, const(int)*, const(float)*,
10383         int, float, const(int*), const(float*),
10384         const(int)*, float, const(int*), const(float),
10385         int*, float, const(int)*, const(int)*,
10386         int, float, int[], float[],
10387         int, float, int[42], float[42],
10388         int, float, const(int)[42], const(float)[42],
10389         int, float, const(int[42]), const(float[42]),
10390         int, float, int[int], float[float],
10391         int, float, int[double], float[double],
10392         int, float, double[int], double[float],
10393         int, float, int function(float, long), float function(float, long),
10394         int, float, int function(float), float function(float),
10395         int, float, int function(float, int), float function(float, float),
10396         int, float, int delegate(float, long), float delegate(float, long),
10397         int, float, int delegate(float), float delegate(float),
10398         int, float, int delegate(float, int), float delegate(float, float),
10399         int, float, Unique!int, Unique!float,
10400         int, float, Tuple!(float, int), Tuple!(float, float),
10401         int, float, RefFun1, RefFun2,
10402         S1, S2,
10403             S1[1][][S1]* function(),
10404             S2[1][][S2]* function(),
10405         int, string,
10406                int[3] function(   int[] arr,    int[2] ...) pure @trusted,
10407             string[3] function(string[] arr, string[2] ...) pure @trusted,
10408     );
10409 
10410     // https://issues.dlang.org/show_bug.cgi?id=15168
10411     static struct T1 { string s; alias s this; }
10412     static struct T2 { char[10] s; alias s this; }
10413     static struct T3 { string[string] s; alias s this; }
10414     alias Pass2 = Test!(
10415         ubyte, ubyte, T1, T1,
10416         ubyte, ubyte, T2, T2,
10417         ubyte, ubyte, T3, T3,
10418     );
10419 }
10420 
10421 // https://issues.dlang.org/show_bug.cgi?id=17116
10422 @safe unittest
10423 {
10424     alias ConstDg = void delegate(float) const;
10425     alias B = void delegate(int) const;
10426     alias A = ReplaceType!(float, int, ConstDg);
10427     static assert(is(B == A));
10428 }
10429 
10430  // https://issues.dlang.org/show_bug.cgi?id=19696
10431 @safe unittest
10432 {
10433     static struct T(U) {}
10434     static struct S { T!int t; alias t this; }
10435     static assert(is(ReplaceType!(float, float, S) == S));
10436 }
10437 
10438  // https://issues.dlang.org/show_bug.cgi?id=19697
10439 @safe unittest
10440 {
10441     class D(T) {}
10442     class C : D!C {}
10443     static assert(is(ReplaceType!(float, float, C)));
10444 }
10445 
10446 // https://issues.dlang.org/show_bug.cgi?id=16132
10447 @safe unittest
10448 {
10449     interface I(T) {}
10450     class C : I!int {}
10451     static assert(is(ReplaceType!(int, string, C) == C));
10452 }
10453 
10454 // https://issues.dlang.org/show_bug.cgi?id=22325
10455 @safe unittest
10456 {
10457     static struct Foo(alias f) {}
10458     static void bar() {}
10459     alias _ = ReplaceType!(int, int, Foo!bar);
10460 }
10461 
10462 /**
10463 Ternary type with three truth values:
10464 
10465 $(UL
10466     $(LI `Ternary.yes` for `true`)
10467     $(LI `Ternary.no` for `false`)
10468     $(LI `Ternary.unknown` as an unknown state)
10469 )
10470 
10471 Also known as trinary, trivalent, or trilean.
10472 
10473 See_Also:
10474     $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
10475         Three Valued Logic on Wikipedia)
10476 */
10477 struct Ternary
10478 {
10479     @safe @nogc nothrow pure:
10480 
10481     private ubyte value = 6;
10482     private static Ternary make(ubyte b)
10483     {
10484         Ternary r = void;
10485         r.value = b;
10486         return r;
10487     }
10488 
10489     /**
10490         The possible states of the `Ternary`
10491     */
10492     enum no = make(0);
10493     /// ditto
10494     enum yes = make(2);
10495     /// ditto
10496     enum unknown = make(6);
10497 
10498     /**
10499      Construct and assign from a `bool`, receiving `no` for `false` and `yes`
10500      for `true`.
10501     */
10502     this(bool b) { value = b << 1; }
10503 
10504     /// ditto
10505     void opAssign(bool b) { value = b << 1; }
10506 
10507     /**
10508     Construct a ternary value from another ternary value
10509     */
10510     this(const Ternary b) { value = b.value; }
10511 
10512     /**
10513     $(TABLE Truth table for logical operations,
10514       $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
10515       $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
10516       $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
10517       $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
10518       $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
10519       $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
10520       $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
10521       $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
10522       $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
10523       $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
10524     )
10525     */
10526     Ternary opUnary(string s)() if (s == "~")
10527     {
10528         return make((386 >> value) & 6);
10529     }
10530 
10531     /// ditto
10532     Ternary opBinary(string s)(Ternary rhs) if (s == "|")
10533     {
10534         return make((25_512 >> (value + rhs.value)) & 6);
10535     }
10536 
10537     /// ditto
10538     Ternary opBinary(string s)(Ternary rhs) if (s == "&")
10539     {
10540         return make((26_144 >> (value + rhs.value)) & 6);
10541     }
10542 
10543     /// ditto
10544     Ternary opBinary(string s)(Ternary rhs) if (s == "^")
10545     {
10546         return make((26_504 >> (value + rhs.value)) & 6);
10547     }
10548 
10549     /// ditto
10550     Ternary opBinary(string s)(bool rhs)
10551     if (s == "|" || s == "&" || s == "^")
10552     {
10553         return this.opBinary!s(Ternary(rhs));
10554     }
10555 }
10556 
10557 ///
10558 @safe @nogc nothrow pure
10559 unittest
10560 {
10561     Ternary a;
10562     assert(a == Ternary.unknown);
10563 
10564     assert(~Ternary.yes == Ternary.no);
10565     assert(~Ternary.no == Ternary.yes);
10566     assert(~Ternary.unknown == Ternary.unknown);
10567 }
10568 
10569 @safe @nogc nothrow pure
10570 unittest
10571 {
10572     alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
10573     Ternary[27] truthTableAnd =
10574     [
10575         t, t, t,
10576         t, u, u,
10577         t, f, f,
10578         u, t, u,
10579         u, u, u,
10580         u, f, f,
10581         f, t, f,
10582         f, u, f,
10583         f, f, f,
10584     ];
10585 
10586     Ternary[27] truthTableOr =
10587     [
10588         t, t, t,
10589         t, u, t,
10590         t, f, t,
10591         u, t, t,
10592         u, u, u,
10593         u, f, u,
10594         f, t, t,
10595         f, u, u,
10596         f, f, f,
10597     ];
10598 
10599     Ternary[27] truthTableXor =
10600     [
10601         t, t, f,
10602         t, u, u,
10603         t, f, t,
10604         u, t, u,
10605         u, u, u,
10606         u, f, u,
10607         f, t, t,
10608         f, u, u,
10609         f, f, f,
10610     ];
10611 
10612     for (auto i = 0; i != truthTableAnd.length; i += 3)
10613     {
10614         assert((truthTableAnd[i] & truthTableAnd[i + 1])
10615             == truthTableAnd[i + 2]);
10616         assert((truthTableOr[i] | truthTableOr[i + 1])
10617             == truthTableOr[i + 2]);
10618         assert((truthTableXor[i] ^ truthTableXor[i + 1])
10619             == truthTableXor[i + 2]);
10620     }
10621 
10622     Ternary a;
10623     assert(a == Ternary.unknown);
10624     static assert(!is(typeof({ if (a) {} })));
10625     assert(!is(typeof({ auto b = Ternary(3); })));
10626     a = true;
10627     assert(a == Ternary.yes);
10628     a = false;
10629     assert(a == Ternary.no);
10630     a = Ternary.unknown;
10631     assert(a == Ternary.unknown);
10632     Ternary b;
10633     b = a;
10634     assert(b == a);
10635     assert(~Ternary.yes == Ternary.no);
10636     assert(~Ternary.no == Ternary.yes);
10637     assert(~Ternary.unknown == Ternary.unknown);
10638 }
10639 
10640 @safe @nogc nothrow pure
10641 unittest
10642 {
10643     Ternary a = Ternary(true);
10644     assert(a == Ternary.yes);
10645     assert((a & false) == Ternary.no);
10646     assert((a | false) == Ternary.yes);
10647     assert((a ^ true) == Ternary.no);
10648     assert((a ^ false) == Ternary.yes);
10649 }
10650 
10651 // https://issues.dlang.org/show_bug.cgi?id=22511
10652 @safe unittest
10653 {
10654     static struct S
10655     {
10656         int b;
10657         @disable this(this);
10658         this(ref return scope inout S rhs) inout
10659         {
10660             this.b = rhs.b + 1;
10661         }
10662     }
10663 
10664     Nullable!S s1 = S(1);
10665     assert(s1.get().b == 2);
10666     Nullable!S s2 = s1;
10667     assert(s2.get().b == 3);
10668 }
10669 
10670 @safe unittest
10671 {
10672     static struct S
10673     {
10674         int b;
10675         this(this) { ++b; }
10676     }
10677 
10678     Nullable!S s1 = S(1);
10679     assert(s1.get().b == 2);
10680     Nullable!S s2 = s1;
10681     assert(s2.get().b == 3);
10682 }
10683 
10684 // https://issues.dlang.org/show_bug.cgi?id=24318
10685 @system unittest
10686 {
10687     static struct S
10688     {
10689         @disable this(this);
10690         int i;
10691     }
10692 
10693     Nullable!S s = S(1);
10694     assert(s.get().i == 1);
10695     s = S(2);
10696     assert(s.get().i == 2);
10697 }
10698 
10699 /// The old version of $(LREF SafeRefCounted), before $(LREF borrow) existed.
10700 /// Old code may be relying on `@safe`ty of some of the member functions which
10701 /// cannot be safe in the new scheme, and
10702 /// can avoid breakage by continuing to use this. `SafeRefCounted` should be
10703 /// preferred, as this type is outdated and unrecommended for new code.
10704 struct RefCounted(T, RefCountedAutoInitialize autoInit =
10705     RefCountedAutoInitialize.yes)
10706 {
10707     version (D_BetterC)
10708     {
10709         private enum enableGCScan = false;
10710     }
10711     else
10712     {
10713         private enum enableGCScan = hasIndirections!T;
10714     }
10715 
10716     extern(C) private pure nothrow @nogc static
10717     {
10718         pragma(mangle, "free") void pureFree( void *ptr );
10719         static if (enableGCScan)
10720             import core.memory : GC;
10721     }
10722 
10723     struct RefCountedStore
10724     {
10725         private struct Impl
10726         {
10727             T _payload;
10728             size_t _count;
10729         }
10730 
10731         private Impl* _store;
10732 
10733         private void initialize(A...)(auto ref A args)
10734         {
10735             import core.lifetime : emplace, forward;
10736 
10737             allocateStore();
10738             version (D_Exceptions) scope(failure) deallocateStore();
10739             emplace(&_store._payload, forward!args);
10740             _store._count = 1;
10741         }
10742 
10743         private void move(ref T source) nothrow pure
10744         {
10745             import std.algorithm.mutation : moveEmplace;
10746 
10747             allocateStore();
10748             moveEmplace(source, _store._payload);
10749             _store._count = 1;
10750         }
10751 
10752         // 'nothrow': can only generate an Error
10753         private void allocateStore() nothrow pure
10754         {
10755             static if (enableGCScan)
10756             {
10757                 import std.internal.memory : enforceCalloc;
10758                 _store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
10759                 GC.addRange(&_store._payload, T.sizeof);
10760             }
10761             else
10762             {
10763                 import std.internal.memory : enforceMalloc;
10764                 _store = cast(Impl*) enforceMalloc(Impl.sizeof);
10765             }
10766         }
10767 
10768         private void deallocateStore() nothrow pure
10769         {
10770             static if (enableGCScan)
10771             {
10772                 GC.removeRange(&this._store._payload);
10773             }
10774             pureFree(_store);
10775             _store = null;
10776         }
10777 
10778         @property nothrow @safe pure @nogc
10779         bool isInitialized() const
10780         {
10781             return _store !is null;
10782         }
10783 
10784         @property nothrow @safe pure @nogc
10785         size_t refCount() const
10786         {
10787             return isInitialized ? _store._count : 0;
10788         }
10789 
10790         void ensureInitialized()()
10791         {
10792             // By checking for `@disable this()` and failing early we can
10793             // produce a clearer error message.
10794             static assert(__traits(compiles, { static T t; }),
10795                 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
10796                 "` because `" ~ fullyQualifiedName!T ~
10797                 ".this()` is annotated with `@disable`.");
10798             if (!isInitialized) initialize();
10799         }
10800 
10801     }
10802     RefCountedStore _refCounted;
10803 
10804     @property nothrow @safe
10805     ref inout(RefCountedStore) refCountedStore() inout
10806     {
10807         return _refCounted;
10808     }
10809 
10810     this(A...)(auto ref A args) if (A.length > 0)
10811     out
10812     {
10813         assert(refCountedStore.isInitialized);
10814     }
10815     do
10816     {
10817         import core.lifetime : forward;
10818         _refCounted.initialize(forward!args);
10819     }
10820 
10821     this(T val)
10822     {
10823         _refCounted.move(val);
10824     }
10825 
10826     this(this) @safe pure nothrow @nogc
10827     {
10828         if (!_refCounted.isInitialized) return;
10829         ++_refCounted._store._count;
10830     }
10831 
10832     ~this()
10833     {
10834         if (!_refCounted.isInitialized) return;
10835         assert(_refCounted._store._count > 0);
10836         if (--_refCounted._store._count)
10837             return;
10838         // Done, destroy and deallocate
10839         .destroy(_refCounted._store._payload);
10840         _refCounted.deallocateStore();
10841     }
10842 
10843     void opAssign(typeof(this) rhs)
10844     {
10845         import std.algorithm.mutation : swap;
10846 
10847         swap(_refCounted._store, rhs._refCounted._store);
10848     }
10849 
10850     void opAssign(T rhs)
10851     {
10852         import std.algorithm.mutation : move;
10853 
10854         static if (autoInit == RefCountedAutoInitialize.yes)
10855         {
10856             _refCounted.ensureInitialized();
10857         }
10858         else
10859         {
10860             assert(_refCounted.isInitialized);
10861         }
10862         move(rhs, _refCounted._store._payload);
10863     }
10864 
10865     static if (autoInit == RefCountedAutoInitialize.yes)
10866     {
10867         //Can't use inout here because of potential mutation
10868         @property
10869         ref T refCountedPayload() return
10870         {
10871             _refCounted.ensureInitialized();
10872             return _refCounted._store._payload;
10873         }
10874     }
10875 
10876     @property nothrow @safe pure @nogc
10877     ref inout(T) refCountedPayload() inout return
10878     {
10879         assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
10880         return _refCounted._store._payload;
10881     }
10882 
10883     alias refCountedPayload this;
10884 
10885     static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
10886     {
10887         string toString(this This)()
10888         {
10889             import std.conv : to;
10890 
10891             static if (autoInit)
10892                 return to!string(refCountedPayload);
10893             else
10894             {
10895                 if (!_refCounted.isInitialized)
10896                     return This.stringof ~ "(RefCountedStore(null))";
10897                 else
10898                     return to!string(_refCounted._store._payload);
10899             }
10900         }
10901     }
10902 }
10903 
10904 ///
10905 @betterC pure @system nothrow @nogc unittest
10906 {
10907     auto rc1 = RefCounted!int(5);
10908     assert(rc1 == 5);
10909     auto rc2 = rc1;
10910     rc2 = 42;
10911     assert(rc1 == 42);
10912 }
10913 
10914 // More unit tests below SafeRefCounted
10915 
10916 /**
10917  * Like $(LREF safeRefCounted) but used to initialize $(LREF RefCounted)
10918  * instead. Intended for backwards compatibility, otherwise it is preferable
10919  *  to use `safeRefCounted`.
10920  */
10921 RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
10922 {
10923     typeof(return) res;
10924     res._refCounted.move(val);
10925     return res;
10926 }
10927 
10928 ///
10929 @system unittest
10930 {
10931     static struct File
10932     {
10933         static size_t nDestroyed;
10934         string name;
10935         @disable this(this); // not copyable
10936         ~this() { name = null; ++nDestroyed; }
10937     }
10938 
10939     auto file = File("name");
10940     assert(file.name == "name");
10941     static assert(!__traits(compiles, {auto file2 = file;}));
10942     assert(File.nDestroyed == 0);
10943 
10944     {
10945         import std.algorithm.mutation : move;
10946         auto rcFile = refCounted(move(file));
10947         assert(rcFile.name == "name");
10948         assert(File.nDestroyed == 1);
10949         assert(file.name == null);
10950 
10951         auto rcFile2 = rcFile;
10952         assert(rcFile.refCountedStore.refCount == 2);
10953         assert(File.nDestroyed == 1);
10954     }
10955 
10956     assert(File.nDestroyed == 2);
10957 }
10958 
10959 // More unit tests below safeRefCounted