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