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