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 {
foo()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 */
Unique(T)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;
thisS264 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 {
~this()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 {
~this()324 ~this() { debug(Unique) writeln(" Bar destructor"); }
val()325 int val() const { return 4; }
326 }
327 alias UBar = Unique!(Bar);
g(UBar u)328 UBar g(UBar u)
329 {
330 debug(Unique) writeln("inside g");
331 return u.release;
332 }
333 auto ub = UBar(new Bar);
334 assert(!ub.isEmpty);
335 assert(ub.val == 4);
336 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
337 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;
this()354 this()
355 {
356 count++;
357 }
~this()358 ~this()
359 {
360 count--;
361 }
val()362 int val() const { return 4; }
363 }
364 alias UBar = Unique!Bar;
g(UBar u)365 UBar g(UBar u)
366 {
367 debug(Unique) writeln("inside g");
368 return u.release;
369 }
consume(UBar u)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 {
~thisFoo394 ~this() { debug(Unique) writeln(" Foo destructor"); }
valFoo395 int val() const { return 3; }
396 @disable this(this);
397 }
398 alias UFoo = Unique!(Foo);
399
f(UFoo u)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 */
Tuple(Specs...)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), …: 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 (__traits(isTemplate, mixin("a."~name)))
5937 {
5938 // member template
5939 template opDispatch(T...)
5940 {
5941 enum targs = T.length ? "!T" : "";
5942 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
5943 }
5944 }
5945 else
5946 {
5947 // field or property function
5948 @property auto ref opDispatch(this X)() { return mixin("a."~name); }
5949 @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
5950 }
5951
5952 }
5953
5954 import std.traits : isArray;
5955
5956 static if (isArray!ValueType)
5957 {
5958 auto opDollar() const { return a.length; }
5959 }
5960 else static if (is(typeof(a.opDollar!0)))
5961 {
5962 auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
5963 }
5964 else static if (is(typeof(a.opDollar) == function))
5965 {
5966 auto ref opDollar() { return a.opDollar(); }
5967 }
5968 else static if (is(typeof(a.opDollar)))
5969 {
5970 alias opDollar = a.opDollar;
5971 }
5972 }
5973
5974 ///
5975 @safe unittest
5976 {
5977 struct MyInt
5978 {
5979 private int value;
5980 mixin Proxy!value;
5981
5982 this(int n){ value = n; }
5983 }
5984
5985 MyInt n = 10;
5986
5987 // Enable operations that original type has.
5988 ++n;
5989 assert(n == 11);
5990 assert(n * 2 == 22);
5991
5992 void func(int n) { }
5993
5994 // Disable implicit conversions to original type.
5995 //int x = n;
5996 //func(n);
5997 }
5998
5999 ///The proxied value must be an $(B lvalue).
6000 @safe unittest
6001 {
6002 struct NewIntType
6003 {
6004 //Won't work; the literal '1'
6005 //is an rvalue, not an lvalue
6006 //mixin Proxy!1;
6007
6008 //Okay, n is an lvalue
6009 int n;
6010 mixin Proxy!n;
6011
6012 this(int n) { this.n = n; }
6013 }
6014
6015 NewIntType nit = 0;
6016 nit++;
6017 assert(nit == 1);
6018
6019
6020 struct NewObjectType
6021 {
6022 Object obj;
6023 //Ok, obj is an lvalue
6024 mixin Proxy!obj;
6025
6026 this (Object o) { obj = o; }
6027 }
6028
6029 NewObjectType not = new Object();
6030 assert(__traits(compiles, not.toHash()));
6031 }
6032
6033 /**
6034 There is one exception to the fact that the new type is not related to the
6035 old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
6036 functions are usable with the new type; they will be forwarded on to the
6037 proxied value.
6038 */
6039 @safe unittest
6040 {
6041 import std.math;
6042
6043 float f = 1.0;
6044 assert(!f.isInfinity);
6045
6046 struct NewFloat
6047 {
6048 float _;
6049 mixin Proxy!_;
6050
6051 this(float f) { _ = f; }
6052 }
6053
6054 NewFloat nf = 1.0f;
6055 assert(!nf.isInfinity);
6056 }
6057
6058 @safe unittest
6059 {
6060 static struct MyInt
6061 {
6062 private int value;
6063 mixin Proxy!value;
6064 this(int n) inout { value = n; }
6065
6066 enum str = "str";
6067 static immutable arr = [1,2,3];
6068 }
6069
6070 foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
6071 {
6072 T m = 10;
6073 static assert(!__traits(compiles, { int x = m; }));
6074 static assert(!__traits(compiles, { void func(int n){} func(m); }));
6075 assert(m == 10);
6076 assert(m != 20);
6077 assert(m < 20);
6078 assert(+m == 10);
6079 assert(-m == -10);
6080 assert(cast(double) m == 10.0);
6081 assert(m + 10 == 20);
6082 assert(m - 5 == 5);
6083 assert(m * 20 == 200);
6084 assert(m / 2 == 5);
6085 assert(10 + m == 20);
6086 assert(15 - m == 5);
6087 assert(20 * m == 200);
6088 assert(50 / m == 5);
6089 static if (is(T == MyInt)) // mutable
6090 {
6091 assert(++m == 11);
6092 assert(m++ == 11); assert(m == 12);
6093 assert(--m == 11);
6094 assert(m-- == 11); assert(m == 10);
6095 m = m;
6096 m = 20; assert(m == 20);
6097 }
6098 static assert(T.max == int.max);
6099 static assert(T.min == int.min);
6100 static assert(T.init == int.init);
6101 static assert(T.str == "str");
6102 static assert(T.arr == [1,2,3]);
6103 }
6104 }
6105 @system unittest
6106 {
6107 static struct MyArray
6108 {
6109 private int[] value;
6110 mixin Proxy!value;
6111 this(int[] arr) { value = arr; }
6112 this(immutable int[] arr) immutable { value = arr; }
6113 }
6114
6115 foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
6116 {
6117 static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
6118 T a = [1,2,3,4].idup; // workaround until qualified ctor is properly supported
6119 else
6120 T a = [1,2,3,4];
6121 assert(a == [1,2,3,4]);
6122 assert(a != [5,6,7,8]);
6123 assert(+a[0] == 1);
6124 version (LittleEndian)
6125 assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
6126 else
6127 assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
6128 assert(a ~ [10,11] == [1,2,3,4,10,11]);
6129 assert(a[0] == 1);
6130 assert(a[] == [1,2,3,4]);
6131 assert(a[2 .. 4] == [3,4]);
6132 static if (is(T == MyArray)) // mutable
6133 {
6134 a = a;
6135 a = [5,6,7,8]; assert(a == [5,6,7,8]);
6136 a[0] = 0; assert(a == [0,6,7,8]);
6137 a[] = 1; assert(a == [1,1,1,1]);
6138 a[0 .. 3] = 2; assert(a == [2,2,2,1]);
6139 a[0] += 2; assert(a == [4,2,2,1]);
6140 a[] *= 2; assert(a == [8,4,4,2]);
6141 a[0 .. 2] /= 2; assert(a == [4,2,4,2]);
6142 }
6143 }
6144 }
6145 @system unittest
6146 {
6147 class Foo
6148 {
6149 int field;
6150
6151 @property int val1() const { return field; }
6152 @property void val1(int n) { field = n; }
6153
6154 @property ref int val2() { return field; }
6155
6156 int func(int x, int y) const { return x; }
6157 void func1(ref int a) { a = 9; }
6158
6159 T ifti1(T)(T t) { return t; }
6160 void ifti2(Args...)(Args args) { }
6161 void ifti3(T, Args...)(Args args) { }
6162
6163 T opCast(T)(){ return T.init; }
6164
6165 T tempfunc(T)() { return T.init; }
6166 }
6167 class Hoge
6168 {
6169 Foo foo;
6170 mixin Proxy!foo;
6171 this(Foo f) { foo = f; }
6172 }
6173
6174 auto h = new Hoge(new Foo());
6175 int n;
6176
6177 static assert(!__traits(compiles, { Foo f = h; }));
6178
6179 // field
6180 h.field = 1; // lhs of assign
6181 n = h.field; // rhs of assign
6182 assert(h.field == 1); // lhs of BinExp
6183 assert(1 == h.field); // rhs of BinExp
6184 assert(n == 1);
6185
6186 // getter/setter property function
6187 h.val1 = 4;
6188 n = h.val1;
6189 assert(h.val1 == 4);
6190 assert(4 == h.val1);
6191 assert(n == 4);
6192
6193 // ref getter property function
6194 h.val2 = 8;
6195 n = h.val2;
6196 assert(h.val2 == 8);
6197 assert(8 == h.val2);
6198 assert(n == 8);
6199
6200 // member function
6201 assert(h.func(2,4) == 2);
6202 h.func1(n);
6203 assert(n == 9);
6204
6205 // IFTI
6206 assert(h.ifti1(4) == 4);
6207 h.ifti2(4);
6208 h.ifti3!int(4, 3);
6209
6210 // bug5896 test
6211 assert(h.opCast!int() == 0);
6212 assert(cast(int) h == 0);
6213 const ih = new const Hoge(new Foo());
6214 static assert(!__traits(compiles, ih.opCast!int()));
6215 static assert(!__traits(compiles, cast(int) ih));
6216
6217 // template member function
6218 assert(h.tempfunc!int() == 0);
6219 }
6220
6221 @system unittest // about Proxy inside a class
6222 {
6223 class MyClass
6224 {
6225 int payload;
6226 mixin Proxy!payload;
6227 this(int i){ payload = i; }
6228 string opCall(string msg){ return msg; }
6229 int pow(int i){ return payload ^^ i; }
6230 }
6231
6232 class MyClass2
6233 {
6234 MyClass payload;
6235 mixin Proxy!payload;
6236 this(int i){ payload = new MyClass(i); }
6237 }
6238
6239 class MyClass3
6240 {
6241 int payload;
6242 mixin Proxy!payload;
6243 this(int i){ payload = i; }
6244 }
6245
6246 // opEquals
6247 Object a = new MyClass(5);
6248 Object b = new MyClass(5);
6249 Object c = new MyClass2(5);
6250 Object d = new MyClass3(5);
6251 assert(a == b);
6252 assert((cast(MyClass) a) == 5);
6253 assert(5 == (cast(MyClass) b));
6254 assert(5 == cast(MyClass2) c);
6255 assert(a != d);
6256
6257 assert(c != a);
6258 // oops! above line is unexpected, isn't it?
6259 // the reason is below.
6260 // MyClass2.opEquals knows MyClass but,
6261 // MyClass.opEquals doesn't know MyClass2.
6262 // so, c.opEquals(a) is true, but a.opEquals(c) is false.
6263 // furthermore, opEquals(T) couldn't be invoked.
6264 assert((cast(MyClass2) c) != (cast(MyClass) a));
6265
6266 // opCmp
6267 Object e = new MyClass2(7);
6268 assert(a < cast(MyClass2) e); // OK. and
6269 assert(e > a); // OK, but...
6270 // assert(a < e); // RUNTIME ERROR!
6271 // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
6272 assert(3 < cast(MyClass) a);
6273 assert((cast(MyClass2) e) < 11);
6274
6275 // opCall
6276 assert((cast(MyClass2) e)("hello") == "hello");
6277
6278 // opCast
6279 assert((cast(MyClass)(cast(MyClass2) c)) == a);
6280 assert((cast(int)(cast(MyClass2) c)) == 5);
6281
6282 // opIndex
6283 class MyClass4
6284 {
6285 string payload;
6286 mixin Proxy!payload;
6287 this(string s){ payload = s; }
6288 }
6289 class MyClass5
6290 {
6291 MyClass4 payload;
6292 mixin Proxy!payload;
6293 this(string s){ payload = new MyClass4(s); }
6294 }
6295 auto f = new MyClass4("hello");
6296 assert(f[1] == 'e');
6297 auto g = new MyClass5("hello");
6298 assert(f[1] == 'e');
6299
6300 // opSlice
6301 assert(f[2 .. 4] == "ll");
6302
6303 // opUnary
6304 assert(-(cast(MyClass2) c) == -5);
6305
6306 // opBinary
6307 assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
6308 assert(5 + cast(MyClass) a == 10);
6309
6310 // opAssign
6311 (cast(MyClass2) c) = 11;
6312 assert((cast(MyClass2) c) == 11);
6313 (cast(MyClass2) c) = new MyClass(13);
6314 assert((cast(MyClass2) c) == 13);
6315
6316 // opOpAssign
6317 assert((cast(MyClass2) c) += 4);
6318 assert((cast(MyClass2) c) == 17);
6319
6320 // opDispatch
6321 assert((cast(MyClass2) c).pow(2) == 289);
6322
6323 // opDollar
6324 assert(f[2..$-1] == "ll");
6325
6326 // toHash
6327 int[Object] hash;
6328 hash[a] = 19;
6329 hash[c] = 21;
6330 assert(hash[b] == 19);
6331 assert(hash[c] == 21);
6332 }
6333
6334 @safe unittest
6335 {
6336 struct MyInt
6337 {
6338 int payload;
6339
6340 mixin Proxy!payload;
6341 }
6342
6343 MyInt v;
6344 v = v;
6345
6346 struct Foo
6347 {
6348 @disable void opAssign(typeof(this));
6349 }
6350 struct MyFoo
6351 {
6352 Foo payload;
6353
6354 mixin Proxy!payload;
6355 }
6356 MyFoo f;
6357 static assert(!__traits(compiles, f = f));
6358
6359 struct MyFoo2
6360 {
6361 Foo payload;
6362
6363 mixin Proxy!payload;
6364
6365 // override default Proxy behavior
6366 void opAssign(typeof(this) rhs){}
6367 }
6368 MyFoo2 f2;
6369 f2 = f2;
6370 }
6371 @safe unittest
6372 {
6373 // bug8613
6374 static struct Name
6375 {
6376 mixin Proxy!val;
6377 private string val;
6378 this(string s) { val = s; }
6379 }
6380
6381 bool[Name] names;
6382 names[Name("a")] = true;
6383 bool* b = Name("a") in names;
6384 }
6385
6386 @system unittest
6387 {
6388 // bug14213, using function for the payload
6389 static struct S
6390 {
6391 int foo() { return 12; }
6392 mixin Proxy!foo;
6393 }
6394 static class C
6395 {
6396 int foo() { return 12; }
6397 mixin Proxy!foo;
6398 }
6399 S s;
6400 assert(s + 1 == 13);
6401 C c = new C();
6402 assert(s * 2 == 24);
6403 }
6404
6405 // Check all floating point comparisons for both Proxy and Typedef,
6406 // also against int and a Typedef!int, to be as regression-proof
6407 // as possible. bug 15561
6408 @safe unittest
6409 {
6410 static struct MyFloatImpl
6411 {
6412 float value;
6413 mixin Proxy!value;
6414 }
6415 static void allFail(T0, T1)(T0 a, T1 b)
6416 {
6417 assert(!(a == b));
6418 assert(!(a<b));
6419 assert(!(a <= b));
6420 assert(!(a>b));
6421 assert(!(a >= b));
6422 }
6423 foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
6424 float, real, Typedef!int, int))
6425 {
6426 foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
6427 {
6428 T1 a;
6429 T2 b;
6430
6431 static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
6432 allFail(a, b);
6433 a = 3;
6434 allFail(a, b);
6435
6436 b = 4;
6437 assert(a != b);
6438 assert(a<b);
6439 assert(a <= b);
6440 assert(!(a>b));
6441 assert(!(a >= b));
6442
6443 a = 4;
6444 assert(a == b);
6445 assert(!(a<b));
6446 assert(a <= b);
6447 assert(!(a>b));
6448 assert(a >= b);
6449 }
6450 }
6451 }
6452
6453 /**
6454 $(B Typedef) allows the creation of a unique type which is
6455 based on an existing type. Unlike the $(D alias) feature,
6456 $(B Typedef) ensures the two types are not considered as equals.
6457
6458 Example:
6459 ----
6460 alias MyInt = Typedef!int;
6461 static void takeInt(int) { }
6462 static void takeMyInt(MyInt) { }
6463
6464 int i;
6465 takeInt(i); // ok
6466 takeMyInt(i); // fails
6467
6468 MyInt myInt;
6469 takeInt(myInt); // fails
6470 takeMyInt(myInt); // ok
6471 ----
6472
6473 Params:
6474
6475 init = Optional initial value for the new type. For example:
6476
6477 ----
6478 alias MyInt = Typedef!(int, 10);
6479 MyInt myInt;
6480 assert(myInt == 10); // default-initialized to 10
6481 ----
6482
6483 cookie = Optional, used to create multiple unique types which are
6484 based on the same origin type $(D T). For example:
6485
6486 ----
6487 alias TypeInt1 = Typedef!int;
6488 alias TypeInt2 = Typedef!int;
6489
6490 // The two Typedefs are the same type.
6491 static assert(is(TypeInt1 == TypeInt2));
6492
6493 alias MoneyEuros = Typedef!(float, float.init, "euros");
6494 alias MoneyDollars = Typedef!(float, float.init, "dollars");
6495
6496 // The two Typedefs are _not_ the same type.
6497 static assert(!is(MoneyEuros == MoneyDollars));
6498 ----
6499
6500 Note: If a library routine cannot handle the Typedef type,
6501 you can use the $(D TypedefType) template to extract the
6502 type which the Typedef wraps.
6503 */
6504 struct Typedef(T, T init = T.init, string cookie=null)
6505 {
6506 private T Typedef_payload = init;
6507
6508 this(T init)
6509 {
6510 Typedef_payload = init;
6511 }
6512
6513 this(Typedef tdef)
6514 {
6515 this(tdef.Typedef_payload);
6516 }
6517
6518 // We need to add special overload for cast(Typedef!X) exp,
6519 // thus we can't simply inherit Proxy!Typedef_payload
6520 T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
6521 {
6522 return T2(cast(T) Typedef_payload);
6523 }
6524
6525 auto ref opCast(T2, this X)()
6526 {
6527 return cast(T2) Typedef_payload;
6528 }
6529
6530 mixin Proxy!Typedef_payload;
6531
6532 pure nothrow @nogc @safe @property
6533 {
6534 alias TD = typeof(this);
6535 static if (isIntegral!T)
6536 {
6537 static TD min() {return TD(T.min);}
6538 static TD max() {return TD(T.max);}
6539 }
6540 else static if (isFloatingPoint!T)
6541 {
6542 static TD infinity() {return TD(T.infinity);}
6543 static TD nan() {return TD(T.nan);}
6544 static TD dig() {return TD(T.dig);}
6545 static TD epsilon() {return TD(T.epsilon);}
6546 static TD mant_dig() {return TD(T.mant_dig);}
6547 static TD max_10_exp() {return TD(T.max_10_exp);}
6548 static TD max_exp() {return TD(T.max_exp);}
6549 static TD min_10_exp() {return TD(T.min_10_exp);}
6550 static TD min_exp() {return TD(T.min_exp);}
6551 static TD max() {return TD(T.max);}
6552 static TD min_normal() {return TD(T.min_normal);}
6553 TD re() {return TD(Typedef_payload.re);}
6554 TD im() {return TD(Typedef_payload.im);}
6555 }
6556 }
6557 }
6558
6559 /**
6560 Get the underlying type which a $(D Typedef) wraps.
6561 If $(D T) is not a $(D Typedef) it will alias itself to $(D T).
6562 */
6563 template TypedefType(T)
6564 {
6565 static if (is(T : Typedef!Arg, Arg))
6566 alias TypedefType = Arg;
6567 else
6568 alias TypedefType = T;
6569 }
6570
6571 ///
6572 @safe unittest
6573 {
6574 import std.typecons : Typedef, TypedefType;
6575 import std.conv : to;
6576
6577 alias MyInt = Typedef!int;
6578 static assert(is(TypedefType!MyInt == int));
6579
6580 /// Instantiating with a non-Typedef will return that type
6581 static assert(is(TypedefType!int == int));
6582
6583 string num = "5";
6584
6585 // extract the needed type
6586 MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
6587 assert(myInt == 5);
6588
6589 // cast to the underlying type to get the value that's being wrapped
6590 int x = cast(TypedefType!MyInt) myInt;
6591
6592 alias MyIntInit = Typedef!(int, 42);
6593 static assert(is(TypedefType!MyIntInit == int));
6594 static assert(MyIntInit() == 42);
6595 }
6596
6597 @safe unittest
6598 {
6599 Typedef!int x = 10;
6600 static assert(!__traits(compiles, { int y = x; }));
6601 static assert(!__traits(compiles, { long z = x; }));
6602
6603 Typedef!int y = 10;
6604 assert(x == y);
6605
6606 static assert(Typedef!int.init == int.init);
6607
6608 Typedef!(float, 1.0) z; // specifies the init
6609 assert(z == 1.0);
6610
6611 static assert(typeof(z).init == 1.0);
6612
6613 alias Dollar = Typedef!(int, 0, "dollar");
6614 alias Yen = Typedef!(int, 0, "yen");
6615 static assert(!is(Dollar == Yen));
6616
6617 Typedef!(int[3]) sa;
6618 static assert(sa.length == 3);
6619 static assert(typeof(sa).length == 3);
6620
6621 Typedef!(int[3]) dollar1;
6622 assert(dollar1[0..$] is dollar1[0 .. 3]);
6623
6624 Typedef!(int[]) dollar2;
6625 dollar2.length = 3;
6626 assert(dollar2[0..$] is dollar2[0 .. 3]);
6627
6628 static struct Dollar1
6629 {
6630 static struct DollarToken {}
6631 enum opDollar = DollarToken.init;
6632 auto opSlice(size_t, DollarToken) { return 1; }
6633 auto opSlice(size_t, size_t) { return 2; }
6634 }
6635
6636 Typedef!Dollar1 drange1;
6637 assert(drange1[0..$] == 1);
6638 assert(drange1[0 .. 1] == 2);
6639
6640 static struct Dollar2
6641 {
6642 size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
6643 size_t opIndex(size_t i, size_t j) { return i + j; }
6644 }
6645
6646 Typedef!Dollar2 drange2;
6647 assert(drange2[$, $] == 101);
6648
6649 static struct Dollar3
6650 {
6651 size_t opDollar() { return 123; }
6652 size_t opIndex(size_t i) { return i; }
6653 }
6654
6655 Typedef!Dollar3 drange3;
6656 assert(drange3[$] == 123);
6657 }
6658
6659 @safe @nogc pure nothrow unittest // Bugzilla 11703
6660 {
6661 alias I = Typedef!int;
6662 static assert(is(typeof(I.min) == I));
6663 static assert(is(typeof(I.max) == I));
6664
6665 alias F = Typedef!double;
6666 static assert(is(typeof(F.infinity) == F));
6667 static assert(is(typeof(F.epsilon) == F));
6668
6669 F f;
6670 assert(!is(typeof(F.re).stringof == double));
6671 assert(!is(typeof(F.im).stringof == double));
6672 }
6673
6674 @safe unittest
6675 {
6676 // bug8655
6677 import std.typecons;
6678 import std.bitmanip;
6679 static import core.stdc.config;
6680
6681 alias c_ulong = Typedef!(core.stdc.config.c_ulong);
6682
6683 static struct Foo
6684 {
6685 mixin(bitfields!(
6686 c_ulong, "NameOffset", 31,
6687 c_ulong, "NameIsString", 1
6688 ));
6689 }
6690 }
6691
6692 @safe unittest // Issue 12596
6693 {
6694 import std.typecons;
6695 alias TD = Typedef!int;
6696 TD x = TD(1);
6697 TD y = TD(x);
6698 assert(x == y);
6699 }
6700
6701 @safe unittest // about toHash
6702 {
6703 import std.typecons;
6704 {
6705 alias TD = Typedef!int;
6706 int[TD] td;
6707 td[TD(1)] = 1;
6708 assert(td[TD(1)] == 1);
6709 }
6710
6711 {
6712 alias TD = Typedef!(int[]);
6713 int[TD] td;
6714 td[TD([1,2,3,4])] = 2;
6715 assert(td[TD([1,2,3,4])] == 2);
6716 }
6717
6718 {
6719 alias TD = Typedef!(int[][]);
6720 int[TD] td;
6721 td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
6722 assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
6723 }
6724
6725 {
6726 struct MyStruct{ int x; }
6727 alias TD = Typedef!MyStruct;
6728 int[TD] td;
6729 td[TD(MyStruct(10))] = 4;
6730 assert(TD(MyStruct(20)) !in td);
6731 assert(td[TD(MyStruct(10))] == 4);
6732 }
6733
6734 {
6735 static struct MyStruct2
6736 {
6737 int x;
6738 size_t toHash() const nothrow @safe { return x; }
6739 bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
6740 }
6741
6742 alias TD = Typedef!MyStruct2;
6743 int[TD] td;
6744 td[TD(MyStruct2(50))] = 5;
6745 assert(td[TD(MyStruct2(50))] == 5);
6746 }
6747
6748 {
6749 class MyClass{}
6750 alias TD = Typedef!MyClass;
6751 int[TD] td;
6752 auto c = new MyClass;
6753 td[TD(c)] = 6;
6754 assert(TD(new MyClass) !in td);
6755 assert(td[TD(c)] == 6);
6756 }
6757 }
6758
6759 @system unittest
6760 {
6761 alias String = Typedef!(char[]);
6762 alias CString = Typedef!(const(char)[]);
6763 CString cs = "fubar";
6764 String s = cast(String) cs;
6765 assert(cs == s);
6766 char[] s2 = cast(char[]) cs;
6767 const(char)[] cs2 = cast(const(char)[])s;
6768 assert(s2 == cs2);
6769 }
6770
6771 /**
6772 Allocates a $(D class) object right inside the current scope,
6773 therefore avoiding the overhead of $(D new). This facility is unsafe;
6774 it is the responsibility of the user to not escape a reference to the
6775 object outside the scope.
6776
6777 The class destructor will be called when the result of `scoped()` is
6778 itself destroyed.
6779
6780 Scoped class instances can be embedded in a parent `class` or `struct`,
6781 just like a child struct instance. Scoped member variables must have
6782 type `typeof(scoped!Class(args))`, and be initialized with a call to
6783 scoped. See below for an example.
6784
6785 Note:
6786 It's illegal to move a class instance even if you are sure there
6787 are no pointers to it. As such, it is illegal to move a scoped object.
6788 */
6789 template scoped(T)
6790 if (is(T == class))
6791 {
6792 // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
6793 // small objects). We will just use the maximum of filed alignments.
6794 alias alignment = classInstanceAlignment!T;
6795 alias aligned = _alignUp!alignment;
6796
6797 static struct Scoped
6798 {
6799 // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
6800 private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
6801
6802 @property inout(T) Scoped_payload() inout
6803 {
6804 void* alignedStore = cast(void*) aligned(cast(uintptr_t) Scoped_store.ptr);
6805 // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
6806 immutable size_t d = alignedStore - Scoped_store.ptr;
6807 size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
6808 if (d != *currD)
6809 {
6810 import core.stdc.string : memmove;
6811 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
6812 *currD = d;
6813 }
6814 return cast(inout(T)) alignedStore;
6815 }
6816 alias Scoped_payload this;
6817
6818 @disable this();
6819 @disable this(this);
6820
6821 ~this()
6822 {
6823 // `destroy` will also write .init but we have no functions in druntime
6824 // for deterministic finalization and memory releasing for now.
6825 .destroy(Scoped_payload);
6826 }
6827 }
6828
6829 /** Returns the _scoped object.
6830 Params: args = Arguments to pass to $(D T)'s constructor.
6831 */
6832 @system auto scoped(Args...)(auto ref Args args)
6833 {
6834 import std.conv : emplace;
6835
6836 Scoped result = void;
6837 void* alignedStore = cast(void*) aligned(cast(uintptr_t) result.Scoped_store.ptr);
6838 immutable size_t d = alignedStore - result.Scoped_store.ptr;
6839 *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
6840 emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], args);
6841 return result;
6842 }
6843 }
6844
6845 ///
6846 @system unittest
6847 {
6848 class A
6849 {
6850 int x;
6851 this() {x = 0;}
6852 this(int i){x = i;}
6853 ~this() {}
6854 }
6855
6856 // Standard usage, constructing A on the stack
6857 auto a1 = scoped!A();
6858 a1.x = 42;
6859
6860 // Result of `scoped` call implicitly converts to a class reference
6861 A aRef = a1;
6862 assert(aRef.x == 42);
6863
6864 // Scoped destruction
6865 {
6866 auto a2 = scoped!A(1);
6867 assert(a2.x == 1);
6868 aRef = a2;
6869 // a2 is destroyed here, calling A's destructor
6870 }
6871 // aRef is now an invalid reference
6872
6873 // Here the temporary scoped A is immediately destroyed.
6874 // This means the reference is then invalid.
6875 version (Bug)
6876 {
6877 // Wrong, should use `auto`
6878 A invalid = scoped!A();
6879 }
6880
6881 // Restrictions
6882 version (Bug)
6883 {
6884 import std.algorithm.mutation : move;
6885 auto invalid = a1.move; // illegal, scoped objects can't be moved
6886 }
6887 static assert(!is(typeof({
6888 auto e1 = a1; // illegal, scoped objects can't be copied
6889 assert([a1][0].x == 42); // ditto
6890 })));
6891 static assert(!is(typeof({
6892 alias ScopedObject = typeof(a1);
6893 auto e2 = ScopedObject(); // illegal, must be built via scoped!A
6894 auto e3 = ScopedObject(1); // ditto
6895 })));
6896
6897 // Use with alias
6898 alias makeScopedA = scoped!A;
6899 auto a3 = makeScopedA();
6900 auto a4 = makeScopedA(1);
6901
6902 // Use as member variable
6903 struct B
6904 {
6905 typeof(scoped!A()) a; // note the trailing parentheses
6906
6907 this(int i)
6908 {
6909 // construct member
6910 a = scoped!A(i);
6911 }
6912 }
6913
6914 // Stack-allocate
6915 auto b1 = B(5);
6916 aRef = b1.a;
6917 assert(aRef.x == 5);
6918 destroy(b1); // calls A's destructor for b1.a
6919 // aRef is now an invalid reference
6920
6921 // Heap-allocate
6922 auto b2 = new B(6);
6923 assert(b2.a.x == 6);
6924 destroy(*b2); // calls A's destructor for b2.a
6925 }
6926
6927 private uintptr_t _alignUp(uintptr_t alignment)(uintptr_t n)
6928 if (alignment > 0 && !((alignment - 1) & alignment))
6929 {
6930 enum badEnd = alignment - 1; // 0b11, 0b111, ...
6931 return (n + badEnd) & ~badEnd;
6932 }
6933
6934 @system unittest // Issue 6580 testcase
6935 {
6936 enum alignment = (void*).alignof;
6937
6938 static class C0 { }
6939 static class C1 { byte b; }
6940 static class C2 { byte[2] b; }
6941 static class C3 { byte[3] b; }
6942 static class C7 { byte[7] b; }
6943 static assert(scoped!C0().sizeof % alignment == 0);
6944 static assert(scoped!C1().sizeof % alignment == 0);
6945 static assert(scoped!C2().sizeof % alignment == 0);
6946 static assert(scoped!C3().sizeof % alignment == 0);
6947 static assert(scoped!C7().sizeof % alignment == 0);
6948
6949 enum longAlignment = long.alignof;
6950 static class C1long
6951 {
6952 long long_; byte byte_ = 4;
6953 this() { }
6954 this(long _long, ref int i) { long_ = _long; ++i; }
6955 }
6956 static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
6957 static assert(scoped!C1long().sizeof % longAlignment == 0);
6958 static assert(scoped!C2long().sizeof % longAlignment == 0);
6959
6960 void alignmentTest()
6961 {
6962 int var = 5;
6963 auto c1long = scoped!C1long(3, var);
6964 assert(var == 6);
6965 auto c2long = scoped!C2long();
6966 assert(cast(uint)&c1long.long_ % longAlignment == 0);
6967 assert(cast(uint)&c2long.long_ % longAlignment == 0);
6968 assert(c1long.long_ == 3 && c1long.byte_ == 4);
6969 assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
6970 }
6971
6972 alignmentTest();
6973
6974 version (DigitalMars)
6975 {
6976 void test(size_t size)
6977 {
6978 import core.stdc.stdlib;
6979 alloca(size);
6980 alignmentTest();
6981 }
6982 foreach (i; 0 .. 10)
6983 test(i);
6984 }
6985 else
6986 {
6987 void test(size_t size)()
6988 {
6989 byte[size] arr;
6990 alignmentTest();
6991 }
6992 foreach (i; AliasSeq!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
6993 test!i();
6994 }
6995 }
6996
6997 @system unittest // Original Issue 6580 testcase
6998 {
6999 class C { int i; byte b; }
7000
7001 auto sa = [scoped!C(), scoped!C()];
7002 assert(cast(uint)&sa[0].i % int.alignof == 0);
7003 assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
7004 }
7005
7006 @system unittest
7007 {
7008 class A { int x = 1; }
7009 auto a1 = scoped!A();
7010 assert(a1.x == 1);
7011 auto a2 = scoped!A();
7012 a1.x = 42;
7013 a2.x = 53;
7014 assert(a1.x == 42);
7015 }
7016
7017 @system unittest
7018 {
7019 class A { int x = 1; this() { x = 2; } }
7020 auto a1 = scoped!A();
7021 assert(a1.x == 2);
7022 auto a2 = scoped!A();
7023 a1.x = 42;
7024 a2.x = 53;
7025 assert(a1.x == 42);
7026 }
7027
7028 @system unittest
7029 {
7030 class A { int x = 1; this(int y) { x = y; } ~this() {} }
7031 auto a1 = scoped!A(5);
7032 assert(a1.x == 5);
7033 auto a2 = scoped!A(42);
7034 a1.x = 42;
7035 a2.x = 53;
7036 assert(a1.x == 42);
7037 }
7038
7039 @system unittest
7040 {
7041 class A { static bool dead; ~this() { dead = true; } }
7042 class B : A { static bool dead; ~this() { dead = true; } }
7043 {
7044 auto b = scoped!B();
7045 }
7046 assert(B.dead, "asdasd");
7047 assert(A.dead, "asdasd");
7048 }
7049
7050 @system unittest // Issue 8039 testcase
7051 {
7052 static int dels;
7053 static struct S { ~this(){ ++dels; } }
7054
7055 static class A { S s; }
7056 dels = 0; { scoped!A(); }
7057 assert(dels == 1);
7058
7059 static class B { S[2] s; }
7060 dels = 0; { scoped!B(); }
7061 assert(dels == 2);
7062
7063 static struct S2 { S[3] s; }
7064 static class C { S2[2] s; }
7065 dels = 0; { scoped!C(); }
7066 assert(dels == 6);
7067
7068 static class D: A { S2[2] s; }
7069 dels = 0; { scoped!D(); }
7070 assert(dels == 1+6);
7071 }
7072
7073 @system unittest
7074 {
7075 // bug4500
7076 class A
7077 {
7078 this() { a = this; }
7079 this(int i) { a = this; }
7080 A a;
7081 bool check() { return this is a; }
7082 }
7083
7084 auto a1 = scoped!A();
7085 assert(a1.check());
7086
7087 auto a2 = scoped!A(1);
7088 assert(a2.check());
7089
7090 a1.a = a1;
7091 assert(a1.check());
7092 }
7093
7094 @system unittest
7095 {
7096 static class A
7097 {
7098 static int sdtor;
7099
7100 this() { ++sdtor; assert(sdtor == 1); }
7101 ~this() { assert(sdtor == 1); --sdtor; }
7102 }
7103
7104 interface Bob {}
7105
7106 static class ABob : A, Bob
7107 {
7108 this() { ++sdtor; assert(sdtor == 2); }
7109 ~this() { assert(sdtor == 2); --sdtor; }
7110 }
7111
7112 A.sdtor = 0;
7113 scope(exit) assert(A.sdtor == 0);
7114 auto abob = scoped!ABob();
7115 }
7116
7117 @safe unittest
7118 {
7119 static class A { this(int) {} }
7120 static assert(!__traits(compiles, scoped!A()));
7121 }
7122
7123 @system unittest
7124 {
7125 static class A { @property inout(int) foo() inout { return 1; } }
7126
7127 auto a1 = scoped!A();
7128 assert(a1.foo == 1);
7129 static assert(is(typeof(a1.foo) == int));
7130
7131 auto a2 = scoped!(const(A))();
7132 assert(a2.foo == 1);
7133 static assert(is(typeof(a2.foo) == const(int)));
7134
7135 auto a3 = scoped!(immutable(A))();
7136 assert(a3.foo == 1);
7137 static assert(is(typeof(a3.foo) == immutable(int)));
7138
7139 const c1 = scoped!A();
7140 assert(c1.foo == 1);
7141 static assert(is(typeof(c1.foo) == const(int)));
7142
7143 const c2 = scoped!(const(A))();
7144 assert(c2.foo == 1);
7145 static assert(is(typeof(c2.foo) == const(int)));
7146
7147 const c3 = scoped!(immutable(A))();
7148 assert(c3.foo == 1);
7149 static assert(is(typeof(c3.foo) == immutable(int)));
7150 }
7151
7152 @system unittest
7153 {
7154 class C { this(ref int val) { assert(val == 3); ++val; } }
7155
7156 int val = 3;
7157 auto s = scoped!C(val);
7158 assert(val == 4);
7159 }
7160
7161 @system unittest
7162 {
7163 class C
7164 {
7165 this(){}
7166 this(int){}
7167 this(int, int){}
7168 }
7169 alias makeScopedC = scoped!C;
7170
7171 auto a = makeScopedC();
7172 auto b = makeScopedC(1);
7173 auto c = makeScopedC(1, 1);
7174
7175 static assert(is(typeof(a) == typeof(b)));
7176 static assert(is(typeof(b) == typeof(c)));
7177 }
7178
7179 /**
7180 Defines a simple, self-documenting yes/no flag. This makes it easy for
7181 APIs to define functions accepting flags without resorting to $(D
7182 bool), which is opaque in calls, and without needing to define an
7183 enumerated type separately. Using $(D Flag!"Name") instead of $(D
7184 bool) makes the flag's meaning visible in calls. Each yes/no flag has
7185 its own type, which makes confusions and mix-ups impossible.
7186
7187 Example:
7188
7189 Code calling $(D getLine) (usually far away from its definition) can't be
7190 understood without looking at the documentation, even by users familiar with
7191 the API:
7192 ----
7193 string getLine(bool keepTerminator)
7194 {
7195 ...
7196 if (keepTerminator) ...
7197 ...
7198 }
7199 ...
7200 auto line = getLine(false);
7201 ----
7202
7203 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
7204 code compiles and runs with erroneous results.
7205
7206 After replacing the boolean parameter with an instantiation of $(D Flag), code
7207 calling $(D getLine) can be easily read and understood even by people not
7208 fluent with the API:
7209
7210 ----
7211 string getLine(Flag!"keepTerminator" keepTerminator)
7212 {
7213 ...
7214 if (keepTerminator) ...
7215 ...
7216 }
7217 ...
7218 auto line = getLine(Yes.keepTerminator);
7219 ----
7220
7221 The structs $(D Yes) and $(D No) are provided as shorthand for
7222 $(D Flag!"Name".yes) and $(D Flag!"Name".no) and are preferred for brevity and
7223 readability. These convenience structs mean it is usually unnecessary and
7224 counterproductive to create an alias of a $(D Flag) as a way of avoiding typing
7225 out the full type while specifying the affirmative or negative options.
7226
7227 Passing categorical data by means of unstructured $(D bool)
7228 parameters is classified under "simple-data coupling" by Steve
7229 McConnell in the $(LUCKY Code Complete) book, along with three other
7230 kinds of coupling. The author argues citing several studies that
7231 coupling has a negative effect on code quality. $(D Flag) offers a
7232 simple structuring method for passing yes/no flags to APIs.
7233 */
7234 template Flag(string name) {
7235 ///
7236 enum Flag : bool
7237 {
7238 /**
7239 When creating a value of type $(D Flag!"Name"), use $(D
7240 Flag!"Name".no) for the negative option. When using a value
7241 of type $(D Flag!"Name"), compare it against $(D
7242 Flag!"Name".no) or just $(D false) or $(D 0). */
7243 no = false,
7244
7245 /** When creating a value of type $(D Flag!"Name"), use $(D
7246 Flag!"Name".yes) for the affirmative option. When using a
7247 value of type $(D Flag!"Name"), compare it against $(D
7248 Flag!"Name".yes).
7249 */
7250 yes = true
7251 }
7252 }
7253
7254 /**
7255 Convenience names that allow using e.g. $(D Yes.encryption) instead of
7256 $(D Flag!"encryption".yes) and $(D No.encryption) instead of $(D
7257 Flag!"encryption".no).
7258 */
7259 struct Yes
7260 {
7261 template opDispatch(string name)
7262 {
7263 enum opDispatch = Flag!name.yes;
7264 }
7265 }
7266 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
7267
7268 /// Ditto
7269 struct No
7270 {
7271 template opDispatch(string name)
7272 {
7273 enum opDispatch = Flag!name.no;
7274 }
7275 }
7276
7277 ///
7278 @safe unittest
7279 {
7280 Flag!"abc" flag1;
7281 assert(flag1 == Flag!"abc".no);
7282 assert(flag1 == No.abc);
7283 assert(!flag1);
7284 if (flag1) assert(false);
7285 flag1 = Yes.abc;
7286 assert(flag1);
7287 if (!flag1) assert(false);
7288 if (flag1) {} else assert(false);
7289 assert(flag1 == Yes.abc);
7290 }
7291
7292 /**
7293 Detect whether an enum is of integral type and has only "flag" values
7294 (i.e. values with a bit count of exactly 1).
7295 Additionally, a zero value is allowed for compatibility with enums including
7296 a "None" value.
7297 */
7298 template isBitFlagEnum(E)
7299 {
7300 static if (is(E Base == enum) && isIntegral!Base)
7301 {
7302 enum isBitFlagEnum = (E.min >= 0) &&
7303 {
7304 foreach (immutable flag; EnumMembers!E)
7305 {
7306 Base value = flag;
7307 value &= value - 1;
7308 if (value != 0) return false;
7309 }
7310 return true;
7311 }();
7312 }
7313 else
7314 {
7315 enum isBitFlagEnum = false;
7316 }
7317 }
7318
7319 ///
7320 @safe pure nothrow unittest
7321 {
7322 enum A
7323 {
7324 None,
7325 A = 1 << 0,
7326 B = 1 << 1,
7327 C = 1 << 2,
7328 D = 1 << 3,
7329 }
7330
7331 static assert(isBitFlagEnum!A);
7332
7333 enum B
7334 {
7335 A,
7336 B,
7337 C,
7338 D // D == 3
7339 }
7340
7341 static assert(!isBitFlagEnum!B);
7342
7343 enum C: double
7344 {
7345 A = 1 << 0,
7346 B = 1 << 1
7347 }
7348
7349 static assert(!isBitFlagEnum!C);
7350 }
7351
7352 /**
7353 A typesafe structure for storing combinations of enum values.
7354
7355 This template defines a simple struct to represent bitwise OR combinations of
7356 enum values. It can be used if all the enum values are integral constants with
7357 a bit count of at most 1, or if the $(D unsafe) parameter is explicitly set to
7358 Yes.
7359 This is much safer than using the enum itself to store
7360 the OR combination, which can produce surprising effects like this:
7361 ----
7362 enum E
7363 {
7364 A = 1 << 0,
7365 B = 1 << 1
7366 }
7367 E e = E.A | E.B;
7368 // will throw SwitchError
7369 final switch (e)
7370 {
7371 case E.A:
7372 return;
7373 case E.B:
7374 return;
7375 }
7376 ----
7377 */
7378 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe) if (unsafe || isBitFlagEnum!(E))
7379 {
7380 @safe @nogc pure nothrow:
7381 private:
7382 enum isBaseEnumType(T) = is(E == T);
7383 alias Base = OriginalType!E;
7384 Base mValue;
7385 static struct Negation
7386 {
7387 @safe @nogc pure nothrow:
7388 private:
7389 Base mValue;
7390
7391 // Prevent non-copy construction outside the module.
7392 @disable this();
7393 this(Base value)
7394 {
7395 mValue = value;
7396 }
7397 }
7398
7399 public:
7400 this(E flag)
7401 {
7402 this = flag;
7403 }
7404
7405 this(T...)(T flags)
7406 if (allSatisfy!(isBaseEnumType, T))
7407 {
7408 this = flags;
7409 }
7410
7411 bool opCast(B: bool)() const
7412 {
7413 return mValue != 0;
7414 }
7415
7416 Base opCast(B)() const
7417 if (isImplicitlyConvertible!(Base, B))
7418 {
7419 return mValue;
7420 }
7421
7422 Negation opUnary(string op)() const
7423 if (op == "~")
7424 {
7425 return Negation(~mValue);
7426 }
7427
7428 auto ref opAssign(T...)(T flags)
7429 if (allSatisfy!(isBaseEnumType, T))
7430 {
7431 mValue = 0;
7432 foreach (E flag; flags)
7433 {
7434 mValue |= flag;
7435 }
7436 return this;
7437 }
7438
7439 auto ref opAssign(E flag)
7440 {
7441 mValue = flag;
7442 return this;
7443 }
7444
7445 auto ref opOpAssign(string op: "|")(BitFlags flags)
7446 {
7447 mValue |= flags.mValue;
7448 return this;
7449 }
7450
7451 auto ref opOpAssign(string op: "&")(BitFlags flags)
7452 {
7453 mValue &= flags.mValue;
7454 return this;
7455 }
7456
7457 auto ref opOpAssign(string op: "|")(E flag)
7458 {
7459 mValue |= flag;
7460 return this;
7461 }
7462
7463 auto ref opOpAssign(string op: "&")(E flag)
7464 {
7465 mValue &= flag;
7466 return this;
7467 }
7468
7469 auto ref opOpAssign(string op: "&")(Negation negatedFlags)
7470 {
7471 mValue &= negatedFlags.mValue;
7472 return this;
7473 }
7474
7475 auto opBinary(string op)(BitFlags flags) const
7476 if (op == "|" || op == "&")
7477 {
7478 BitFlags result = this;
7479 result.opOpAssign!op(flags);
7480 return result;
7481 }
7482
7483 auto opBinary(string op)(E flag) const
7484 if (op == "|" || op == "&")
7485 {
7486 BitFlags result = this;
7487 result.opOpAssign!op(flag);
7488 return result;
7489 }
7490
7491 auto opBinary(string op: "&")(Negation negatedFlags) const
7492 {
7493 BitFlags result = this;
7494 result.opOpAssign!op(negatedFlags);
7495 return result;
7496 }
7497
7498 auto opBinaryRight(string op)(E flag) const
7499 if (op == "|" || op == "&")
7500 {
7501 return opBinary!op(flag);
7502 }
7503 }
7504
7505 /// BitFlags can be manipulated with the usual operators
7506 @safe @nogc pure nothrow unittest
7507 {
7508 import std.traits : EnumMembers;
7509
7510 // You can use such an enum with BitFlags straight away
7511 enum Enum
7512 {
7513 None,
7514 A = 1 << 0,
7515 B = 1 << 1,
7516 C = 1 << 2
7517 }
7518 BitFlags!Enum flags1;
7519 assert(!(flags1 & (Enum.A | Enum.B | Enum.C)));
7520
7521 // You need to specify the `unsafe` parameter for enum with custom values
7522 enum UnsafeEnum
7523 {
7524 A,
7525 B,
7526 C,
7527 D = B|C
7528 }
7529 static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags2; }));
7530 BitFlags!(UnsafeEnum, Yes.unsafe) flags3;
7531
7532 immutable BitFlags!Enum flags_empty;
7533 // A default constructed BitFlags has no value set
7534 assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
7535
7536 // Value can be set with the | operator
7537 immutable BitFlags!Enum flags_A = flags_empty | Enum.A;
7538
7539 // And tested with the & operator
7540 assert(flags_A & Enum.A);
7541
7542 // Which commutes
7543 assert(Enum.A & flags_A);
7544
7545 // BitFlags can be variadically initialized
7546 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
7547 assert((flags_AB & Enum.A) && (flags_AB & Enum.B) && !(flags_AB & Enum.C));
7548
7549 // Use the ~ operator for subtracting flags
7550 immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
7551 assert(!(flags_B & Enum.A) && (flags_B & Enum.B) && !(flags_B & Enum.C));
7552
7553 // You can use the EnumMembers template to set all flags
7554 immutable BitFlags!Enum flags_all = EnumMembers!Enum;
7555
7556 // use & between BitFlags for intersection
7557 immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
7558 assert(flags_B == (flags_BC & flags_AB));
7559
7560 // All the binary operators work in their assignment version
7561 BitFlags!Enum temp = flags_empty;
7562 temp |= flags_AB;
7563 assert(temp == (flags_empty | flags_AB));
7564 temp = flags_empty;
7565 temp |= Enum.B;
7566 assert(temp == (flags_empty | Enum.B));
7567 temp = flags_empty;
7568 temp &= flags_AB;
7569 assert(temp == (flags_empty & flags_AB));
7570 temp = flags_empty;
7571 temp &= Enum.A;
7572 assert(temp == (flags_empty & Enum.A));
7573
7574 // BitFlags with no value set evaluate to false
7575 assert(!flags_empty);
7576
7577 // BitFlags with at least one value set evaluate to true
7578 assert(flags_A);
7579
7580 // This can be useful to check intersection between BitFlags
7581 assert(flags_A & flags_AB);
7582 assert(flags_AB & Enum.A);
7583
7584 // Finally, you can of course get you raw value out of flags
7585 auto value = cast(int) flags_A;
7586 assert(value == Enum.A);
7587 }
7588
7589 // ReplaceType
7590 /**
7591 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
7592 example, $(D ReplaceType!(int, uint, Tuple!(int, float)[string])) yields
7593 $(D Tuple!(uint, float)[string]). The types in which replacement is performed
7594 may be arbitrarily complex, including qualifiers, built-in type constructors
7595 (pointers, arrays, associative arrays, functions, and delegates), and template
7596 instantiations; replacement proceeds transitively through the type definition.
7597 However, member types in `struct`s or `class`es are not replaced because there
7598 are no ways to express the types resulting after replacement.
7599
7600 This is an advanced type manipulation necessary e.g. for replacing the
7601 placeholder type `This` in $(REF Algebraic, std,variant).
7602
7603 Returns: `ReplaceType` aliases itself to the type(s) that result after
7604 replacement.
7605 */
7606 template ReplaceType(From, To, T...)
7607 {
7608 static if (T.length == 1)
7609 {
7610 static if (is(T[0] == From))
7611 alias ReplaceType = To;
7612 else static if (is(T[0] == const(U), U))
7613 alias ReplaceType = const(ReplaceType!(From, To, U));
7614 else static if (is(T[0] == immutable(U), U))
7615 alias ReplaceType = immutable(ReplaceType!(From, To, U));
7616 else static if (is(T[0] == shared(U), U))
7617 alias ReplaceType = shared(ReplaceType!(From, To, U));
7618 else static if (is(T[0] == U*, U))
7619 {
7620 static if (is(U == function))
7621 alias ReplaceType = replaceTypeInFunctionType!(From, To, T[0]);
7622 else
7623 alias ReplaceType = ReplaceType!(From, To, U)*;
7624 }
7625 else static if (is(T[0] == delegate))
7626 {
7627 alias ReplaceType = replaceTypeInFunctionType!(From, To, T[0]);
7628 }
7629 else static if (is(T[0] == function))
7630 {
7631 static assert(0, "Function types not supported," ~
7632 " use a function pointer type instead of " ~ T[0].stringof);
7633 }
7634 else static if (is(T[0] : U!V, alias U, V...))
7635 {
7636 template replaceTemplateArgs(T...)
7637 {
7638 static if (is(typeof(T[0]))) // template argument is value or symbol
7639 enum replaceTemplateArgs = T[0];
7640 else
7641 alias replaceTemplateArgs = ReplaceType!(From, To, T[0]);
7642 }
7643 alias ReplaceType = U!(staticMap!(replaceTemplateArgs, V));
7644 }
7645 else static if (is(T[0] == struct))
7646 // don't match with alias this struct below (Issue 15168)
7647 alias ReplaceType = T[0];
7648 else static if (is(T[0] == U[], U))
7649 alias ReplaceType = ReplaceType!(From, To, U)[];
7650 else static if (is(T[0] == U[n], U, size_t n))
7651 alias ReplaceType = ReplaceType!(From, To, U)[n];
7652 else static if (is(T[0] == U[V], U, V))
7653 alias ReplaceType =
7654 ReplaceType!(From, To, U)[ReplaceType!(From, To, V)];
7655 else
7656 alias ReplaceType = T[0];
7657 }
7658 else static if (T.length > 1)
7659 {
7660 alias ReplaceType = AliasSeq!(ReplaceType!(From, To, T[0]),
7661 ReplaceType!(From, To, T[1 .. $]));
7662 }
7663 else
7664 {
7665 alias ReplaceType = AliasSeq!();
7666 }
7667 }
7668
7669 ///
7670 @safe unittest
7671 {
7672 static assert(
7673 is(ReplaceType!(int, string, int[]) == string[]) &&
7674 is(ReplaceType!(int, string, int[int]) == string[string]) &&
7675 is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
7676 is(ReplaceType!(int, string, Tuple!(int[], float))
7677 == Tuple!(string[], float))
7678 );
7679 }
7680
7681 private template replaceTypeInFunctionType(From, To, fun)
7682 {
7683 alias RX = ReplaceType!(From, To, ReturnType!fun);
7684 alias PX = AliasSeq!(ReplaceType!(From, To, Parameters!fun));
7685 // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
7686 // tuple if Parameters!fun.length == 1
7687
7688 string gen()
7689 {
7690 enum linkage = functionLinkage!fun;
7691 alias attributes = functionAttributes!fun;
7692 enum variadicStyle = variadicFunctionStyle!fun;
7693 alias storageClasses = ParameterStorageClassTuple!fun;
7694
7695 string result;
7696
7697 result ~= "extern(" ~ linkage ~ ") ";
7698 static if (attributes & FunctionAttribute.ref_)
7699 {
7700 result ~= "ref ";
7701 }
7702
7703 result ~= "RX";
7704 static if (is(fun == delegate))
7705 result ~= " delegate";
7706 else
7707 result ~= " function";
7708
7709 result ~= "(";
7710 foreach (i, _; PX)
7711 {
7712 if (i)
7713 result ~= ", ";
7714 if (storageClasses[i] & ParameterStorageClass.scope_)
7715 result ~= "scope ";
7716 if (storageClasses[i] & ParameterStorageClass.out_)
7717 result ~= "out ";
7718 if (storageClasses[i] & ParameterStorageClass.ref_)
7719 result ~= "ref ";
7720 if (storageClasses[i] & ParameterStorageClass.lazy_)
7721 result ~= "lazy ";
7722 if (storageClasses[i] & ParameterStorageClass.return_)
7723 result ~= "return ";
7724
7725 result ~= "PX[" ~ i.stringof ~ "]";
7726 }
7727 static if (variadicStyle == Variadic.typesafe)
7728 result ~= " ...";
7729 else static if (variadicStyle != Variadic.no)
7730 result ~= ", ...";
7731 result ~= ")";
7732
7733 static if (attributes & FunctionAttribute.pure_)
7734 result ~= " pure";
7735 static if (attributes & FunctionAttribute.nothrow_)
7736 result ~= " nothrow";
7737 static if (attributes & FunctionAttribute.property)
7738 result ~= " @property";
7739 static if (attributes & FunctionAttribute.trusted)
7740 result ~= " @trusted";
7741 static if (attributes & FunctionAttribute.safe)
7742 result ~= " @safe";
7743 static if (attributes & FunctionAttribute.nogc)
7744 result ~= " @nogc";
7745 static if (attributes & FunctionAttribute.system)
7746 result ~= " @system";
7747 static if (attributes & FunctionAttribute.const_)
7748 result ~= " const";
7749 static if (attributes & FunctionAttribute.immutable_)
7750 result ~= " immutable";
7751 static if (attributes & FunctionAttribute.inout_)
7752 result ~= " inout";
7753 static if (attributes & FunctionAttribute.shared_)
7754 result ~= " shared";
7755 static if (attributes & FunctionAttribute.return_)
7756 result ~= " return";
7757
7758 return result;
7759 }
7760 //pragma(msg, "gen ==> ", gen());
7761
7762 mixin("alias replaceTypeInFunctionType = " ~ gen() ~ ";");
7763 }
7764
7765 @safe unittest
7766 {
7767 template Test(Ts...)
7768 {
7769 static if (Ts.length)
7770 {
7771 //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
7772 // ~Ts[1].stringof~", "~Ts[2].stringof~")");
7773 static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
7774 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
7775 ~Ts[2].stringof~") == "
7776 ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
7777 alias Test = Test!(Ts[4 .. $]);
7778 }
7779 else alias Test = void;
7780 }
7781
7782 //import core.stdc.stdio;
7783 alias RefFun1 = ref int function(float, long);
7784 alias RefFun2 = ref float function(float, long);
7785 extern(C) int printf(const char*, ...) nothrow @nogc @system;
7786 extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
7787 int func(float);
7788
7789 int x;
7790 struct S1 { void foo() { x = 1; } }
7791 struct S2 { void bar() { x = 2; } }
7792
7793 alias Pass = Test!(
7794 int, float, typeof(&func), float delegate(float),
7795 int, float, typeof(&printf), typeof(&floatPrintf),
7796 int, float, int function(out long, ...),
7797 float function(out long, ...),
7798 int, float, int function(ref float, long),
7799 float function(ref float, long),
7800 int, float, int function(ref int, long),
7801 float function(ref float, long),
7802 int, float, int function(out int, long),
7803 float function(out float, long),
7804 int, float, int function(lazy int, long),
7805 float function(lazy float, long),
7806 int, float, int function(out long, ref const int),
7807 float function(out long, ref const float),
7808 int, int, int, int,
7809 int, float, int, float,
7810 int, float, const int, const float,
7811 int, float, immutable int, immutable float,
7812 int, float, shared int, shared float,
7813 int, float, int*, float*,
7814 int, float, const(int)*, const(float)*,
7815 int, float, const(int*), const(float*),
7816 const(int)*, float, const(int*), const(float),
7817 int*, float, const(int)*, const(int)*,
7818 int, float, int[], float[],
7819 int, float, int[42], float[42],
7820 int, float, const(int)[42], const(float)[42],
7821 int, float, const(int[42]), const(float[42]),
7822 int, float, int[int], float[float],
7823 int, float, int[double], float[double],
7824 int, float, double[int], double[float],
7825 int, float, int function(float, long), float function(float, long),
7826 int, float, int function(float), float function(float),
7827 int, float, int function(float, int), float function(float, float),
7828 int, float, int delegate(float, long), float delegate(float, long),
7829 int, float, int delegate(float), float delegate(float),
7830 int, float, int delegate(float, int), float delegate(float, float),
7831 int, float, Unique!int, Unique!float,
7832 int, float, Tuple!(float, int), Tuple!(float, float),
7833 int, float, RefFun1, RefFun2,
7834 S1, S2,
7835 S1[1][][S1]* function(),
7836 S2[1][][S2]* function(),
7837 int, string,
7838 int[3] function( int[] arr, int[2] ...) pure @trusted,
7839 string[3] function(string[] arr, string[2] ...) pure @trusted,
7840 );
7841
7842 // Bugzilla 15168
7843 static struct T1 { string s; alias s this; }
7844 static struct T2 { char[10] s; alias s this; }
7845 static struct T3 { string[string] s; alias s this; }
7846 alias Pass2 = Test!(
7847 ubyte, ubyte, T1, T1,
7848 ubyte, ubyte, T2, T2,
7849 ubyte, ubyte, T3, T3,
7850 );
7851 }
7852
7853 @safe unittest // Bugzilla 17116
7854 {
7855 alias ConstDg = void delegate(float) const;
7856 alias B = void delegate(int) const;
7857 alias A = ReplaceType!(float, int, ConstDg);
7858 static assert(is(B == A));
7859 }
7860
7861 /**
7862 Ternary type with three truth values:
7863
7864 $(UL
7865 $(LI `Ternary.yes` for `true`)
7866 $(LI `Ternary.no` for `false`)
7867 $(LI `Ternary.unknown` as an unknown state)
7868 )
7869
7870 Also known as trinary, trivalent, or trilean.
7871
7872 See_Also:
7873 $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
7874 Three Valued Logic on Wikipedia)
7875 */
7876 struct Ternary
7877 {
7878 @safe @nogc nothrow pure:
7879
7880 private ubyte value = 6;
7881 private static Ternary make(ubyte b)
7882 {
7883 Ternary r = void;
7884 r.value = b;
7885 return r;
7886 }
7887
7888 /**
7889 The possible states of the `Ternary`
7890 */
7891 enum no = make(0);
7892 /// ditto
7893 enum yes = make(2);
7894 /// ditto
7895 enum unknown = make(6);
7896
7897 /**
7898 Construct and assign from a `bool`, receiving `no` for `false` and `yes`
7899 for `true`.
7900 */
7901 this(bool b) { value = b << 1; }
7902
7903 /// ditto
7904 void opAssign(bool b) { value = b << 1; }
7905
7906 /**
7907 Construct a ternary value from another ternary value
7908 */
7909 this(const Ternary b) { value = b.value; }
7910
7911 /**
7912 $(TABLE Truth table for logical operations,
7913 $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
7914 $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
7915 $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
7916 $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
7917 $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
7918 $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
7919 $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
7920 $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
7921 $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
7922 $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
7923 )
7924 */
7925 Ternary opUnary(string s)() if (s == "~")
7926 {
7927 return make((386 >> value) & 6);
7928 }
7929
7930 /// ditto
7931 Ternary opBinary(string s)(Ternary rhs) if (s == "|")
7932 {
7933 return make((25_512 >> (value + rhs.value)) & 6);
7934 }
7935
7936 /// ditto
7937 Ternary opBinary(string s)(Ternary rhs) if (s == "&")
7938 {
7939 return make((26_144 >> (value + rhs.value)) & 6);
7940 }
7941
7942 /// ditto
7943 Ternary opBinary(string s)(Ternary rhs) if (s == "^")
7944 {
7945 return make((26_504 >> (value + rhs.value)) & 6);
7946 }
7947 }
7948
7949 ///
7950 @safe @nogc nothrow pure
7951 unittest
7952 {
7953 Ternary a;
7954 assert(a == Ternary.unknown);
7955
7956 assert(~Ternary.yes == Ternary.no);
7957 assert(~Ternary.no == Ternary.yes);
7958 assert(~Ternary.unknown == Ternary.unknown);
7959 }
7960
7961 @safe @nogc nothrow pure
7962 unittest
7963 {
7964 alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
7965 Ternary[27] truthTableAnd =
7966 [
7967 t, t, t,
7968 t, u, u,
7969 t, f, f,
7970 u, t, u,
7971 u, u, u,
7972 u, f, f,
7973 f, t, f,
7974 f, u, f,
7975 f, f, f,
7976 ];
7977
7978 Ternary[27] truthTableOr =
7979 [
7980 t, t, t,
7981 t, u, t,
7982 t, f, t,
7983 u, t, t,
7984 u, u, u,
7985 u, f, u,
7986 f, t, t,
7987 f, u, u,
7988 f, f, f,
7989 ];
7990
7991 Ternary[27] truthTableXor =
7992 [
7993 t, t, f,
7994 t, u, u,
7995 t, f, t,
7996 u, t, u,
7997 u, u, u,
7998 u, f, u,
7999 f, t, t,
8000 f, u, u,
8001 f, f, f,
8002 ];
8003
8004 for (auto i = 0; i != truthTableAnd.length; i += 3)
8005 {
8006 assert((truthTableAnd[i] & truthTableAnd[i + 1])
8007 == truthTableAnd[i + 2]);
8008 assert((truthTableOr[i] | truthTableOr[i + 1])
8009 == truthTableOr[i + 2]);
8010 assert((truthTableXor[i] ^ truthTableXor[i + 1])
8011 == truthTableXor[i + 2]);
8012 }
8013
8014 Ternary a;
8015 assert(a == Ternary.unknown);
8016 static assert(!is(typeof({ if (a) {} })));
8017 assert(!is(typeof({ auto b = Ternary(3); })));
8018 a = true;
8019 assert(a == Ternary.yes);
8020 a = false;
8021 assert(a == Ternary.no);
8022 a = Ternary.unknown;
8023 assert(a == Ternary.unknown);
8024 Ternary b;
8025 b = a;
8026 assert(b == a);
8027 assert(~Ternary.yes == Ternary.no);
8028 assert(~Ternary.no == Ternary.yes);
8029 assert(~Ternary.unknown == Ternary.unknown);
8030 }
8031