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