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