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