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