root/trunk/phobos/std/typecons.d

Revision 2232, 68.7 kB (checked in by braddr, 3 years ago)

A bunch of 64 bit fixes, including disabling tests that don't pass

  • Property svn:eol-style set to native
Line 
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 Macros:
8
9 WIKI = Phobos/StdVariant
10
11 Synopsis:
12
13 ----
14 // value tuples
15 alias Tuple!(float, "x", float, "y", float, "z") Coord;
16 Coord c;
17 c[1] = 1;       // access by index
18 c.z = 1;        // access by given name
19 alias Tuple!(string, string) DicEntry; // names can be omitted
20
21 // Rebindable references to const and immutable objects
22 void bar()
23 {
24     const w1 = new Widget, w2 = new Widget;
25     w1.foo();
26     // w1 = w2 would not work; can't rebind const object
27     auto r = Rebindable!(const Widget)(w1);
28     // invoke method as if r were a Widget object
29     r.foo();
30     // rebind r to refer to another object
31     r = w2;
32 }
33 ----
34
35 Copyright: Copyright the respective authors, 2008-
36 License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
37 Authors:   $(WEB erdani.org, Andrei Alexandrescu),
38            $(WEB bartoszmilewski.wordpress.com, Bartosz Milewski),
39            Don Clugston,
40            Shin Fujishiro
41  */
42 module std.typecons;
43 import core.memory, core.stdc.stdlib;
44 import std.algorithm, std.array, std.conv, std.exception, std.format,
45     std.metastrings, std.stdio, std.traits, std.typetuple, std.range;
46
47 version(unittest) import core.vararg;
48
49 /**
50 Encapsulates unique ownership of a resource.  Resource of type T is
51 deleted at the end of the scope, unless it is transferred.  The
52 transfer can be explicit, by calling $(D release), or implicit, when
53 returning Unique from a function. The resource can be a polymorphic
54 class object, in which case Unique behaves polymorphically too.
55
56 Example:
57 */
58
59 struct Unique(T)
60 {
61 static if (is(T:Object))
62     alias T RefT;
63 else
64     alias T * RefT;
65 public:
66 /+ Doesn't work yet
67     /**
68     The safe constructor. It creates the resource and
69     guarantees unique ownership of it (unless the constructor
70     of $(D T) publishes aliases of $(D this)),
71     */
72     this(A...)(A args)
73     {
74         _p = new T(args);
75     }
76 +/
77
78     /**
79     Constructor that takes an rvalue.
80     It will ensure uniqueness, as long as the rvalue
81     isn't just a view on an lvalue (e.g., a cast)
82     Typical usage:
83     ----
84     Unique!(Foo) f = new Foo;
85     ----
86     */
87     this(RefT p)
88     {
89         writeln("Unique constructor with rvalue");
90         _p = p;
91     }
92     /**
93     Constructor that takes an lvalue. It nulls its source.
94     The nulling will ensure uniqueness as long as there
95     are no previous aliases to the source.
96     */
97     this(ref RefT p)
98     {
99         _p = p;
100         writeln("Unique constructor nulling source");
101         p = null;
102         assert(p is null);
103     }
104 /+ Doesn't work yet
105     /**
106     Constructor that takes a Unique of a type that is convertible to our type:
107     Disallow construction from lvalue (force the use of release on the source Unique)
108     If the source is an rvalue, null its content, so the destrutctor doesn't delete it
109
110     Typically used by the compiler to return $(D Unique) of derived type as $(D Unique)
111     of base type.
112
113     Example:
114     ----
115     Unique!(Base) create()
116     {
117         Unique!(Derived) d = new Derived;
118         return d; // Implicit Derived->Base conversion
119     }
120     ----
121     */
122     this(U)(ref Unique!(U) u) = null;
123     this(U)(Unique!(U) u)
124     {
125         _p = u._p;
126         u._p = null;
127     }
128 +/
129
130     ~this()
131     {
132         writeln("Unique destructor of ", (_p is null)? null: _p);
133         delete _p;
134         _p = null;
135     }
136     bool isEmpty() const
137     {
138         return _p is null;
139     }
140     /** Returns a unique rvalue. Nullifies the current contents */
141     Unique release()
142     {
143         writeln("Release");
144         auto u = Unique(_p);
145         assert(_p is null);
146         writeln("return from Release");
147         return u;
148     }
149     /** Forwards member access to contents */
150     RefT opDot() { return _p; }
151
152 /+ doesn't work yet!
153     /**
154     Postblit operator is undefined to prevent the cloning of $(D Unique) objects
155     */
156     this(this) = null;
157  +/
158
159 private:
160     RefT _p;
161 }
162
163 /+ doesn't work yet
164 unittest
165 {
166     writeln("Unique class");
167     class Bar
168     {
169         ~this() { writefln("    Bar destructor"); }
170         int val() const { return 4; }
171     }
172     alias Unique!(Bar) UBar;
173     UBar g(UBar u)
174     {
175         return u;
176     }
177     auto ub = UBar(new Bar);
178     assert(!ub.isEmpty);
179     assert(ub.val == 4);
180     // should not compile
181     // auto ub3 = g(ub);
182     writeln("Calling g");
183     auto ub2 = g(ub.release);
184     assert(ub.isEmpty);
185     assert(!ub2.isEmpty);
186 }
187
188 unittest
189 {
190     writeln("Unique struct");
191     struct Foo
192     {
193         ~this() { writefln("    Bar destructor"); }
194         int val() const { return 3; }
195     }
196     alias Unique!(Foo) UFoo;
197
198     UFoo f(UFoo u)
199     {
200         writeln("inside f");
201         return u;
202     }
203
204     auto uf = UFoo(new Foo);
205     assert(!uf.isEmpty);
206     assert(uf.val == 3);
207     // should not compile
208     // auto uf3 = f(uf);
209     writeln("Unique struct: calling f");
210     auto uf2 = f(uf.release);
211     assert(uf.isEmpty);
212     assert(!uf2.isEmpty);
213 }
214 +/
215
216
217 /**
218 Tuple of values, for example $(D Tuple!(int, string)) is a record that
219 stores an $(D int) and a $(D string). $(D Tuple) can be used to bundle
220 values together, notably when returning multiple values from a
221 function. If $(D obj) is a tuple, the individual members are
222 accessible with the syntax $(D obj[0]) for the first field, $(D obj[1])
223 for the second, and so on.
224
225 The choice of zero-based indexing instead of one-base indexing was
226 motivated by the ability to use value tuples with various compile-time
227 loop constructs (e.g. type tuple iteration), all of which use
228 zero-based indexing.
229
230 Example:
231
232 ----
233 Tuple!(int, int) point;
234 // assign coordinates
235 point[0] = 5;
236 point[1] = 6;
237 // read coordinates
238 auto x = point[0];
239 auto y = point[1];
240 ----
241
242 Tuple members can be named. It is legal to mix named and unnamed
243 members. The method above is still applicable to all fields.
244
245 Example:
246
247 ----
248 alias Tuple!(int, "index", string, "value") Entry;
249 Entry e;
250 e.index = 4;
251 e.value = "Hello";
252 assert(e[1] == "Hello");
253 assert(e[0] == 4);
254 ----
255
256 Tuples with named fields are distinct types from tuples with unnamed
257 fields, i.e. each naming imparts a separate type for the tuple. Two
258 tuple differing in naming only are still distinct, even though they
259 might have the same structure.
260
261 Example:
262
263 ----
264 Tuple!(int, "x", int, "y") point1;
265 Tuple!(int, int) point2;
266 assert(!is(typeof(point1) == typeof(point2))); // passes
267 ----
268 */
269 struct Tuple(Specs...)
270 {
271 private:
272
273     // Parse (type,name) pairs (FieldSpecs) out of the specified
274     // arguments. Some fields would have name, others not.
275     template parseSpecs(Specs...)
276     {
277         static if (Specs.length == 0)
278         {
279             alias TypeTuple!() parseSpecs;
280         }
281         else static if (is(Specs[0]))
282         {
283             static if (is(typeof(Specs[1]) : string))
284             {
285                 alias TypeTuple!(FieldSpec!(Specs[0 .. 2]),
286                                  parseSpecs!(Specs[2 .. $])) parseSpecs;
287             }
288             else
289             {
290                 alias TypeTuple!(FieldSpec!(Specs[0]),
291                                  parseSpecs!(Specs[1 .. $])) parseSpecs;
292             }
293         }
294         else
295         {
296             static assert(0, "Attempted to instantiate Tuple with an "
297                             ~"invalid argument: "~ Specs[0].stringof);
298         }
299     }
300
301     template FieldSpec(T, string s = "")
302     {
303         alias T Type;
304         alias s name;
305     }
306
307     alias parseSpecs!Specs fieldSpecs;
308
309     // Used with staticMap.
310     template extractType(alias spec) { alias spec.Type extractType; }
311     template extractName(alias spec) { alias spec.name extractName; }
312
313     // Generates named fields as follows:
314     //    alias Identity!(field[0]) name_0;
315     //    alias Identity!(field[1]) name_1;
316     //      :
317     // NOTE: field[k] is an expression (which yields a symbol of a
318     //       variable) and can't be aliased directly.
319     static string injectNamedFields()
320     {
321         string decl = "";
322         foreach (i, name; staticMap!(extractName, fieldSpecs))
323         {
324             auto    field = text("Identity!(field[", i, "])");
325             auto numbered = text("_", i);
326             decl ~= text("alias ", field, " ", numbered, ";");
327             if (name.length != 0)
328             {
329                 decl ~= text("alias ", numbered, " ", name, ";");
330             }
331         }
332         return decl;
333     }
334
335     // Returns Specs for a subtuple this[from .. to] preserving field
336     // names if any.
337     template sliceSpecs(size_t from, size_t to)
338     {
339         alias staticMap!(expandSpec,
340                          fieldSpecs[from .. to]) sliceSpecs;
341     }
342
343     template expandSpec(alias spec)
344     {
345         static if (spec.name.length == 0)
346         {
347             alias TypeTuple!(spec.Type) expandSpec;
348         }
349         else
350         {
351             alias TypeTuple!(spec.Type, spec.name) expandSpec;
352         }
353     }
354
355 public:
356 /**
357    The type of the tuple's components.
358 */
359     alias staticMap!(extractType, fieldSpecs) Types;
360
361     Types field;
362     mixin(injectNamedFields());
363     alias field expand;
364     alias field this;
365
366     // This mitigates breakage of old code now that std.range.Zip uses
367     // Tuple instead of the old Proxy.  It's intentionally lacking ddoc
368     // because it should eventually be deprecated.
369     auto at(size_t index)() {
370         return field[index];
371     }
372
373 /**
374    Constructor taking one value for each field. Each argument must be
375    implicitly assignable to the respective element of the target.
376  */
377     this(U...)(U values) if (U.length == Types.length)
378     {
379         foreach (i, Unused; Types)
380         {
381             field[i] = values[i];
382         }
383     }
384
385 /**
386    Constructor taking a compatible tuple. Each element of the source
387    must be implicitly assignable to the respective element of the
388    target.
389  */
390     this(U)(U another) if (isTuple!U)
391     {
392         static assert(field.length == another.field.length,
393                       "Length mismatch in attempting to construct a "
394                       ~ typeof(this).stringof ~" with a "~ U.stringof);
395         foreach (i, T; Types)
396         {
397             field[i] = another.field[i];
398         }
399     }
400
401 /**
402    Comparison for equality.
403  */
404     bool opEquals(R)(R rhs) if (isTuple!R)
405     {
406         static assert(field.length == rhs.field.length,
407                 "Length mismatch in attempting to compare a "
408                 ~typeof(this).stringof
409                 ~" with a "~typeof(rhs).stringof);
410         foreach (i, Unused; Types)
411         {
412             if (field[i] != rhs.field[i]) return false;
413         }
414         return true;
415     }
416
417 /**
418    Comparison for ordering.
419  */
420     int opCmp(R)(R rhs) if (isTuple!R)
421     {
422         static assert(field.length == rhs.field.length,
423                 "Length mismatch in attempting to compare a "
424                 ~typeof(this).stringof
425                 ~" with a "~typeof(rhs).stringof);
426         foreach (i, Unused; Types)
427         {
428             if (field[i] != rhs.field[i])
429             {
430                 return field[i] < rhs.field[i] ? -1 : 1;
431             }
432         }
433         return 0;
434     }
435
436 /**
437    Assignment from another tuple. Each element of the source must be
438    implicitly assignable to the respective element of the target.
439  */
440     void opAssign(R)(R rhs) if (isTuple!R)
441     {
442         static assert(field.length == rhs.field.length,
443                       "Length mismatch in attempting to assign a "
444                      ~ R.stringof ~" to a "~ typeof(this).stringof);
445         // Do not swap; opAssign should be called on the fields.
446         foreach (i, Unused; Types)
447         {
448             field[i] = rhs.field[i];
449         }
450     }
451
452     deprecated void assign(R)(R rhs) if (isTuple!R)
453     {
454         this = rhs;
455     }
456
457     // @@@BUG4424@@@ workaround
458     private mixin template _workaround4424()
459     {
460         @disable void opAssign(typeof(this) );
461     }
462     mixin _workaround4424;
463
464 /**
465    Takes a slice of the tuple.
466
467    Example:
468
469 ----
470 Tuple!(int, string, float, double) a;
471 a[1] = "abc";
472 a[2] = 4.5;
473 auto s = a.slice!(1, 3);
474 static assert(is(typeof(s) == Tuple!(string, float)));
475 assert(s[0] == "abc" && s[1] == 4.5);
476 ----
477  */
478     @property
479     ref Tuple!(sliceSpecs!(from, to)) slice(uint from, uint to)()
480     {
481         return *cast(typeof(return) *) &(field[from]);
482     }
483
484 /**
485    The length of the tuple.
486  */
487     enum length = field.length;
488
489 /**
490    Converts to string.
491  */
492     string toString()
493     {
494         enum header = typeof(this).stringof ~ "(",
495              footer = ")",
496              separator = ", ";
497         Appender!string app;
498         app.put(header);
499         foreach (i, Unused; Types)
500         {
501             static if (i > 0)
502             {
503                 app.put(separator);
504             }
505             // TODO: Change this once toString() works for shared objects.
506             static if (is(Unused == class) && is(Unused == shared))
507                 formattedWrite(app, "%s", field[i].stringof);
508             else
509                 formattedWrite(app, "%s", field[i]);
510         }
511         app.put(footer);
512         return app.data;
513     }
514 }
515
516 private template Identity(alias T)
517 {
518     alias T Identity;
519 }
520
521 unittest
522 {
523     {
524         Tuple!(int, "a", int, "b") nosh;
525         static assert(nosh.length == 2);
526         nosh.a = 5;
527         nosh.b = 6;
528         assert(nosh.a == 5);
529         assert(nosh.b == 6);
530     }
531     {
532         Tuple!(short, double) b;
533         static assert(b.length == 2);
534         b[1] = 5;
535         auto a = Tuple!(int, real)(b);
536         assert(a[0] == 0 && a[1] == 5);
537         a = Tuple!(int, real)(1, 2);
538         assert(a[0] == 1 && a[1] == 2);
539         auto c = Tuple!(int, "a", double, "b")(a);
540         assert(c[0] == 1 && c[1] == 2);
541     }
542     {
543         Tuple!(int, real) nosh;
544         nosh[0] = 5;
545         nosh[1] = 0;
546         assert(nosh[0] == 5 && nosh[1] == 0);
547         assert(nosh.toString == "Tuple!(int,real)(5, 0)", nosh.toString);
548         Tuple!(int, int) yessh;
549         nosh = yessh;
550     }
551     {
552         Tuple!(int, "a", double, "b") x;
553         static assert(x.a.offsetof == x[0].offsetof);
554         static assert(x.b.offsetof == x[1].offsetof);
555         x.b = 4.5;
556         x.a = 5;
557         assert(x[0] == 5 && x[1] == 4.5);
558         assert(x.a == 5 && x.b == 4.5);
559     }
560     // indexing
561     {
562         Tuple!(int, real) t;
563         static assert(is(typeof(t[0]) == int));
564         static assert(is(typeof(t[1]) == real));
565         int* p0 = &t[0];
566         real* p1 = &t[1];
567         t[0] = 10;
568         t[1] = -200.0L;
569         assert(*p0 == t[0]);
570         assert(*p1 == t[1]);
571     }
572     // slicing
573     {
574         Tuple!(int, "x", real, "y", double, "z", string) t;
575         t[0] = 10;
576         t[1] = 11;
577         t[2] = 12;
578         t[3] = "abc";
579         auto a = t.slice!(0, 3);
580         assert(a.length == 3);
581         assert(a.x == t.x);
582         assert(a.y == t.y);
583         assert(a.z == t.z);
584         auto b = t.slice!(2, 4);
585         assert(b.length == 2);
586         assert(b.z == t.z);
587         assert(b[1] == t[3]);
588     }
589     // nesting
590     {
591         Tuple!(Tuple!(int, real), Tuple!(string, "s")) t;
592         static assert(is(typeof(t[0]) == Tuple!(int, real)));
593         static assert(is(typeof(t[1]) == Tuple!(string, "s")));
594         static assert(is(typeof(t[0][0]) == int));
595         static assert(is(typeof(t[0][1]) == real));
596         static assert(is(typeof(t[1].s) == string));
597         t[0] = tuple(10, 20.0L);
598         t[1].s = "abc";
599         assert(t[0][0] == 10);
600         assert(t[0][1] == 20.0L);
601         assert(t[1].s == "abc");
602     }
603     // non-POD
604     {
605         static struct S
606         {
607             int count;
608             this(this) { ++count; }
609             ~this() { --count; }
610             void opAssign(S rhs) { count = rhs.count; }
611         }
612         Tuple!(S, S) ss;
613         Tuple!(S, S) ssCopy = ss;
614         assert(ssCopy[0].count == 1);
615         assert(ssCopy[1].count == 1);
616         ssCopy[1] = ssCopy[0];
617         assert(ssCopy[1].count == 2);
618     }
619     // bug 2800
620     {
621         static struct R
622         {
623             Tuple!(int, int) _front;
624             @property ref Tuple!(int, int) front() { return _front;  }
625             @property bool empty() { return _front[0] >= 10; }
626             void popFront() { ++_front[0]; }
627         }
628         foreach (a; R())
629         {
630             static assert(is(typeof(a) == Tuple!(int, int)));
631             assert(0 <= a[0] && a[0] < 10);
632             assert(a[1] == 0);
633         }
634     }
635     // Construction with compatible tuple
636     {
637         Tuple!(int, int) x;
638         x[0] = 10;
639         x[1] = 20;
640         Tuple!(int, "a", double, "b") y = x;
641         assert(y.a == 10);
642         assert(y.b == 20);
643         // incompatible
644         static assert(!__traits(compiles, Tuple!(int, int)(y)));
645     }
646 }
647
648 /**
649 Returns a $(D Tuple) object instantiated and initialized according to
650 the arguments.
651
652 Example:
653 ----
654 auto value = tuple(5, 6.7, "hello");
655 assert(value[0] == 5);
656 assert(value[1] == 6.7);
657 assert(value[2] == "hello");
658 ----
659 */
660
661 Tuple!(T) tuple(T...)(T args)
662 {
663     typeof(return) result;
664     static if (T.length > 0) result.field = args;
665     return result;
666 }
667
668 /**
669 Returns $(D true) if and only if $(D T) is an instance of the
670 $(D Tuple) struct template.
671  */
672 template isTuple(T)
673 {
674     static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
675     {
676         enum isTuple = true;
677     }
678     else
679     {
680         enum isTuple = false;
681     }
682 }
683
684 unittest
685 {
686     static assert(isTuple!(Tuple!()));
687     static assert(isTuple!(Tuple!(int)));
688     static assert(isTuple!(Tuple!(int, real, string)));
689     static assert(isTuple!(Tuple!(int, "x", real, "y")));
690     static assert(isTuple!(Tuple!(int, Tuple!(real), string)));
691
692     static assert(isTuple!(const Tuple!(int)));
693     static assert(isTuple!(immutable Tuple!(int)));
694
695     static assert(!isTuple!(int));
696     static assert(!isTuple!(const int));
697
698     struct S {}
699     static assert(!isTuple!(S));
700 }
701
702
703 private template enumValuesImpl(string name, BaseType, long index, T...)
704 {
705     static if (name.length)
706     {
707         enum string enumValuesImpl = "enum "~name~" : "~BaseType.stringof
708             ~" { "~enumValuesImpl!("", BaseType, index, T)~"}\n";
709     }
710     else
711     {
712         static if (!T.length)
713         {
714             enum string enumValuesImpl = "";
715         }
716         else
717         {
718             static if (T.length == 1
719                        || T.length > 1 && is(typeof(T[1]) : string))
720             {
721                 enum string enumValuesImpl =  T[0]~" = "~ToString!(index)~", "
722                     ~enumValuesImpl!("", BaseType, index + 1, T[1 .. $]);
723             }
724             else
725             {
726                 enum string enumValuesImpl = T[0]~" = "~ToString!(T[1])~", "
727                     ~enumValuesImpl!("", BaseType, T[1] + 1, T[2 .. $]);
728             }
729         }
730     }
731 }
732
733 private template enumParserImpl(string name, bool first, T...)
734 {
735     static if (first)
736     {
737         enum string enumParserImpl = "bool enumFromString(string s, ref "
738             ~name~" v) {\n"
739             ~enumParserImpl!(name, false, T)
740             ~"return false;\n}\n";
741     }
742     else
743     {
744         static if (T.length)
745             enum string enumParserImpl =
746                 "if (s == `"~T[0]~"`) return (v = "~name~"."~T[0]~"), true;\n"
747                 ~enumParserImpl!(name, false, T[1 .. $]);
748         else
749             enum string enumParserImpl = "";
750     }
751 }
752
753 private template enumPrinterImpl(string name, bool first, T...)
754 {
755     static if (first)
756     {
757         enum string enumPrinterImpl = "string enumToString("~name~" v) {\n"
758             ~enumPrinterImpl!(name, false, T)~"\n}\n";
759     }
760     else
761     {
762         static if (T.length)
763             enum string enumPrinterImpl =
764                 "if (v == "~name~"."~T[0]~") return `"~T[0]~"`;\n"
765                 ~enumPrinterImpl!(name, false, T[1 .. $]);
766         else
767             enum string enumPrinterImpl = "return null;";
768     }
769 }
770
771 private template ValueTuple(T...)
772 {
773     alias T ValueTuple;
774 }
775
776 private template StringsOnly(T...)
777 {
778     static if (T.length == 1)
779         static if (is(typeof(T[0]) : string))
780             alias ValueTuple!(T[0]) StringsOnly;
781         else
782             alias ValueTuple!() StringsOnly;
783     else
784         static if (is(typeof(T[0]) : string))
785             alias ValueTuple!(T[0], StringsOnly!(T[1 .. $])) StringsOnly;
786         else
787             alias ValueTuple!(StringsOnly!(T[1 .. $])) StringsOnly;
788 }
789
790 /**
791 Defines truly named enumerated values with parsing and stringizing
792 primitives.
793
794 Example:
795
796 ----
797 mixin(defineEnum!("Abc", "A", "B", 5, "C"));
798 ----
799
800 is equivalent to the following code:
801
802 ----
803 enum Abc { A, B = 5, C }
804 string enumToString(Abc v) { ... }
805 Abc enumFromString(string s) { ... }
806 ----
807
808 The $(D enumToString) function generates the unqualified names
809 of the enumerated values, i.e. "A", "B", and "C". The $(D
810 enumFromString) function expects one of "A", "B", and "C", and throws
811 an exception in any other case.
812
813 A base type can be specified for the enumeration like this:
814
815 ----
816 mixin(defineEnum!("Abc", ubyte, "A", "B", "C", 255));
817 ----
818
819 In this case the generated $(D enum) will have a $(D ubyte)
820 representation.  */
821
822 deprecated template defineEnum(string name, T...)
823 {
824     static if (is(typeof(cast(T[0]) T[0].init)))
825         enum string defineEnum =
826             enumValuesImpl!(name, T[0], 0, T[1 .. $])
827             ~ enumParserImpl!(name, true, StringsOnly!(T[1 .. $]))
828             ~ enumPrinterImpl!(name, true, StringsOnly!(T[1 .. $]));
829     else
830         alias defineEnum!(name, int, T) defineEnum;
831 }
832
833 unittest
834 {
835     mixin(defineEnum!("_24b455e148a38a847d65006bca25f7fe",
836                       "A1", 1, "B1", "C1"));
837     auto a = _24b455e148a38a847d65006bca25f7fe.A1;
838     assert(enumToString(a) == "A1");
839     _24b455e148a38a847d65006bca25f7fe b;
840     assert(enumFromString("B1", b)
841            && b == _24b455e148a38a847d65006bca25f7fe.B1);
842 }
843
844 /**
845 $(D Rebindable!(T)) is a simple, efficient wrapper that behaves just
846 like an object of type $(D T), except that you can reassign it to
847 refer to another object. For completeness, $(D Rebindable!(T)) aliases
848 itself away to $(D T) if $(D T) is a non-const object type. However,
849 $(D Rebindable!(T)) does not compile if $(D T) is a non-class type.
850
851 Regular $(D const) object references cannot be reassigned:
852
853 ----
854 class Widget { int x; int y() const { return a; } }
855 const a = new Widget;
856 a.y();          // fine
857 a.x = 5;        // error! can't modify const a
858 a = new Widget; // error! can't modify const a
859 ----
860
861 However, $(D Rebindable!(Widget)) does allow reassignment, while
862 otherwise behaving exactly like a $(D const Widget):
863
864 ----
865 auto a = Rebindable!(const Widget)(new Widget);
866 a.y();          // fine
867 a.x = 5;        // error! can't modify const a
868 a = new Widget; // fine
869 ----
870
871 You may want to use $(D Rebindable) when you want to have mutable
872 storage referring to $(D const) objects, for example an array of
873 references that must be sorted in place. $(D Rebindable) does not
874 break the soundness of D's type system and does not incur any of the
875 risks usually associated with $(D cast).
876
877  */
878 template Rebindable(T) if (is(T == class) || is(T == interface) || isArray!(T))
879 {
880     static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))
881     {
882         alias T Rebindable;
883     }
884     else static if (isArray!(T))
885     {
886         alias const(ElementType!(T))[] Rebindable;
887     }
888     else
889     {
890         struct Rebindable
891         {
892             private union
893             {
894                 T original;
895                 U stripped;
896             }
897             void opAssign(T another)
898             {
899                 stripped = cast(U) another;
900             }
901             void opAssign(Rebindable another)
902             {
903                 stripped = another.stripped;
904             }
905             static if (is(T == const U))
906             {
907                 // safely assign immutable to const
908                 void opAssign(Rebindable!(immutable U) another)
909                 {
910                     stripped = another.stripped;
911                 }
912             }
913             this(T initializer)
914             {
915                 opAssign(initializer);
916             }
917
918             @property ref T get() {
919                 return original;
920             }
921
922             alias get this;
923         }
924     }
925 }
926
927 /**
928 Convenience function for creating a $(D Rebindable) using automatic type
929 inference.
930 */
931 Rebindable!(T) rebindable(T)(T obj)
932 if (is(T == class) || is(T == interface) || isArray!(T))
933 {
934     typeof(return) ret;
935     ret = obj;
936     return ret;
937 }
938
939 /**
940 This function simply returns the $(D Rebindable) object passed in.  It's useful
941 in generic programming cases when a given object may be either a regular
942 $(D class) or a $(D Rebindable).
943 */
944 Rebindable!(T) rebindable(T)(Rebindable!(T) obj)
945 {
946     return obj;
947 }
948
949 unittest
950 {
951     interface CI { const int foo(); }
952     class C : CI { int foo() const { return 42; } }
953     Rebindable!(C) obj0;
954     static assert(is(typeof(obj0) == C));
955
956     Rebindable!(const(C)) obj1;
957     static assert(is(typeof(obj1.get) == const(C)), typeof(obj1.get).stringof);
958     static assert(is(typeof(obj1.stripped) == C));
959     obj1 = new C;
960     assert(obj1.get !is null);
961     obj1 = new const(C);
962     assert(obj1.get !is null);
963
964     Rebindable!(immutable(C)) obj2;
965     static assert(is(typeof(obj2.get) == immutable(C)));
966     static assert(is(typeof(obj2.stripped) == C));
967     obj2 = new immutable(C);
968     assert(obj1.get !is null);
969
970     // test opDot
971     assert(obj2.foo == 42);
972
973     interface I { final int foo() const { return 42; } }
974     Rebindable!(I) obj3;
975     static assert(is(typeof(obj3) == I));
976
977     Rebindable!(const I) obj4;
978     static assert(is(typeof(obj4.get) == const I));
979     static assert(is(typeof(obj4.stripped) == I));
980     static assert(is(typeof(obj4.foo()) == int));
981     obj4 = new class I {};
982
983     Rebindable!(immutable C) obj5i;
984     Rebindable!(const C) obj5c;
985     obj5c = obj5c;
986     obj5c = obj5i;
987     obj5i = obj5i;
988     static assert(!__traits(compiles, obj5i = obj5c));
989
990     // Test the convenience functions.
991     auto obj5convenience = rebindable(obj5i);
992     assert(obj5convenience is obj5i);
993
994     auto obj6 = rebindable(new immutable(C));
995     static assert(is(typeof(obj6) == Rebindable!(immutable C)));
996     assert(obj6.foo == 42);
997
998     auto obj7 = rebindable(new C);
999     CI interface1 = obj7;
1000     auto interfaceRebind1 = rebindable(interface1);
1001     assert(interfaceRebind1.foo == 42);
1002
1003     const interface2 = interface1;
1004     auto interfaceRebind2 = rebindable(interface2);
1005     assert(interfaceRebind2.foo == 42);
1006
1007     auto arr = [1,2,3,4,5];
1008     const arrConst = arr;
1009     assert(rebindable(arr) == arr);
1010     assert(rebindable(arrConst) == arr);
1011 }
1012
1013 /**
1014   Order the provided members to minimize size while preserving alignment.
1015   Returns a declaration to be mixed in.
1016
1017 Example:
1018 ---
1019 struct Banner {
1020   mixin(alignForSize!(byte[6], double)(["name", "height"]));
1021 }
1022 ---
1023
1024   Alignment is not always optimal for 80-bit reals, nor for structs declared
1025   as align(1).
1026   BUG: bugzilla 2029 prevents the signature from being (string[] names...),
1027   so we need to use an ugly array literal instead.
1028 */
1029 char [] alignForSize(E...)(string[E.length] names)
1030 {
1031     // Sort all of the members by .alignof.
1032     // BUG: Alignment is not always optimal for align(1) structs
1033     // or 80-bit reals.
1034     // TRICK: Use the fact that .alignof is always a power of 2,
1035     // and maximum 16 on extant systems. Thus, we can perform
1036     // a very limited radix sort.
1037     // Contains the members with .alignof = 64,32,16,8,4,2,1
1038     int [][] alignlist; // workaround for bugzilla 2569
1039     alignlist = [ [],[],[],[],[],[],[]]; // workaround for bugzilla 2562
1040     char[][] declaration;
1041     foreach(int i_bug,T; E) {
1042         int i = i_bug; // workaround for bugzilla 2564 (D2 only)
1043         declaration ~= T.stringof ~ " " ~ names[i].dup ~ ";\n";
1044         int a = T.alignof;
1045         int k = a>=64? 0 : a>=32? 1 : a>=16? 2 : a>=8? 3 : a>=4? 4 : a>=2? 5 : 6;
1046         alignlist[k]~=i;
1047     }
1048     char [] s;
1049     foreach(q; alignlist) {
1050       foreach(int i; q) {
1051         s~=  declaration[i];
1052       }
1053     }
1054     return s;
1055 }
1056
1057 unittest {
1058     // assert(alignForSize!(int[], char[3], short, double[5])(["x", "y","z", "w"]) =="double[5u] w;\nint[] x;\nshort z;\nchar[3u] y;\n");
1059     struct Foo{ int x; }
1060     // assert(alignForSize!(ubyte, Foo, cdouble)(["x", "y","z"]) =="cdouble z;\nFoo y;\nubyte x;\n");
1061 }
1062
1063 /*--*
1064 First-class reference type
1065 */
1066 struct Ref(T)
1067 {
1068     private T * _p;
1069     this(ref T value) { _p = &value; }
1070     ref T opDot() { return *_p; }
1071     /*ref*/ T opImplicitCastTo() { return *_p; }
1072     ref T value() { return *_p; }
1073
1074     void opAssign(T value)
1075     {
1076         *_p = value;
1077     }
1078     void opAssign(T * value)
1079     {
1080         _p = value;
1081     }
1082 }
1083
1084 unittest
1085 {
1086     Ref!(int) x;
1087     int y = 42;
1088     x = &y;
1089     assert(x.value == 42);
1090     x = 5;
1091     assert(x.value == 5);
1092     assert(y == 5);
1093 }
1094
1095 /+
1096
1097 /**
1098 Defines a value paired with a distinctive "null" state that denotes
1099 the absence of a valud value. If default constructed, a $(D
1100 Nullable!T) object starts in the null state. Assigning it renders it
1101 non-null. Calling $(D nullify) can nullify it again.
1102
1103 Example:
1104 ----
1105 Nullable!int a;
1106 assert(a.isNull);
1107 a = 5;
1108 assert(!a.isNull);
1109 assert(a == 5);
1110 ----
1111
1112 Practically $(D Nullable!T) stores a $(D T) and a $(D bool).
1113  */
1114 struct Nullable(T)
1115 {
1116     private T _value;
1117     private bool _isNull = true;
1118
1119 /**
1120 Constructor initializing $(D this) with $(D value).
1121  */
1122     this(T value)
1123     {
1124         _value = value;
1125         _isNull = false;
1126     }
1127
1128 /**
1129 Returns $(D true) if and only if $(D this) is in the null state.
1130  */
1131     bool isNull()
1132     {
1133         return _isNull;
1134     }
1135
1136 /**
1137 Forces $(D this) to the null state.
1138  */
1139     void nullify()
1140     {
1141         // destroy
1142         //static if (is(typeof(_value.__dtor()))) _value.__dtor();
1143         _isNull = true;
1144     }
1145
1146 /**
1147 Assigns $(D value) to the internally-held state. If the assignment
1148 succeeds, $(D this) becomes non-null.
1149  */
1150     void opAssign(T value)
1151     {
1152         _value = value;
1153         _isNull = false;
1154     }
1155
1156 /**
1157 Gets the value. Throws an exception if $(D this) is in the null
1158 state. This function is also called for the implicit conversion to $(D
1159 T).
1160  */
1161     ref T get()
1162     {
1163         enforce(!isNull);
1164         return _value;
1165     }
1166
1167 /**
1168 Implicitly converts to $(D T). Throws an exception if $(D this) is in
1169 the null state.
1170  */
1171     alias get this;
1172 }
1173
1174 unittest
1175 {
1176     Nullable!int a;
1177     assert(a.isNull);
1178     a = 5;
1179     assert(!a.isNull);
1180     assert(a == 5);
1181 }
1182
1183 /**
1184 Just like $(D Nullable!T), except that the null state is defined as a
1185 particular value. For example, $(D Nullable!(uint, uint.max)) is an
1186 $(D uint) that sets aside the value $(D uint.max) to denote a null
1187 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
1188 Nullable!T) because it does not need to store an extra $(D bool).
1189  */
1190 struct Nullable(T, T nullValue)
1191 {
1192     private T _value = nullValue;
1193
1194 /**
1195 Constructor initializing $(D this) with $(D value).
1196  */
1197     this(T value)
1198     {
1199         _value = value;
1200     }
1201
1202 /**
1203 Returns $(D true) if and only if $(D this) is in the null state.
1204  */
1205     bool isNull()
1206     {
1207         return _value == nullValue;
1208     }
1209
1210 /**
1211 Forces $(D this) to the null state.
1212  */
1213     void nullify()
1214     {
1215         _value = nullValue;
1216     }
1217
1218 /**
1219 Assigns $(D value) to the internally-held state. No null checks are
1220 made.
1221  */
1222     void opAssign(T value)
1223     {
1224         _value = value;
1225     }
1226
1227 /**
1228 Gets the value. Throws an exception if $(D this) is in the null
1229 state. This function is also called for the implicit conversion to $(D
1230 T).
1231  */
1232     ref T get()
1233     {
1234         enforce(!isNull);
1235         return _value;
1236     }
1237
1238 /**
1239 Implicitly converts to $(D T). Throws an exception if $(D this) is in
1240 the null state.
1241  */
1242     alias get this;
1243 }
1244
1245 unittest
1246 {
1247     Nullable!(int, int.min) a;
1248     assert(a.isNull);
1249     a = 5;
1250     assert(!a.isNull);
1251     assert(a == 5);
1252 }
1253
1254 /**
1255 Just like $(D Nullable!T), except that the object refers to a value
1256 sitting elsewhere in memory. This makes assignments overwrite the
1257 initially assigned value. Internally $(D NullableRef!T) only stores a
1258 pointer to $(D T) (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
1259  */
1260 struct NullableRef(T)
1261 {
1262     private T* _value;
1263
1264 /**
1265 Constructor binding $(D this) with $(D value).
1266  */
1267     this(T * value)
1268     {
1269         _value = value;
1270     }
1271
1272 /**
1273 Binds the internal state to $(D value).
1274  */
1275     void bind(T * value)
1276     {
1277         _value = value;
1278     }
1279
1280 /**
1281 Returns $(D true) if and only if $(D this) is in the null state.
1282  */
1283     bool isNull()
1284     {
1285         return _value is null;
1286     }
1287
1288 /**
1289 Forces $(D this) to the null state.
1290  */
1291     void nullify()
1292     {
1293         _value = null;
1294     }
1295
1296 /**
1297 Assigns $(D value) to the internally-held state.
1298  */
1299     void opAssign(T value)
1300     {
1301         enforce(_value);
1302         *_value = value;
1303     }
1304
1305 /**
1306 Gets the value. Throws an exception if $(D this) is in the null
1307 state. This function is also called for the implicit conversion to $(D
1308 T).
1309  */
1310     ref T get()
1311     {
1312         enforce(!isNull);
1313         return *_value;
1314     }
1315
1316 /**
1317 Implicitly converts to $(D T). Throws an exception if $(D this) is in
1318 the null state.
1319  */
1320     alias get this;
1321 }
1322
1323 unittest
1324 {
1325     int x = 5;
1326     auto a = NullableRef!(int)(&x);
1327     assert(!a.isNull);
1328     assert(a == 5);
1329     a = 42;
1330     assert(!a.isNull);
1331     assert(a == 42);
1332 }
1333
1334 +/
1335
1336
1337 /**
1338 $(D BlackHole!Base) is a subclass of $(D Base) which automatically implements
1339 all abstract member functions in $(D Base) as do-nothing functions.  Each
1340 auto-implemented function just returns the default value of the return type
1341 without doing anything.
1342
1343 The name came from
1344 $(WEB search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
1345 Perl module by Sean M. Burke.
1346
1347 Example:
1348 --------------------
1349 abstract class C
1350 {
1351     int m_value;
1352     this(int v) { m_value = v; }
1353     int value() @property { return m_value; }
1354
1355     abstract real realValue() @property;
1356     abstract void doSomething();
1357 }
1358
1359 void main()
1360 {
1361     auto c = new BlackHole!C(42);
1362     writeln(c.value);     // prints "42"
1363
1364     // Abstract functions are implemented as do-nothing:
1365     writeln(c.realValue); // prints "NaN"
1366     c.doSomething();      // does nothing
1367 }
1368 --------------------
1369
1370 See_Also:
1371   AutoImplement, generateEmptyFunction
1372  */
1373 template BlackHole(Base)
1374 {
1375     alias AutoImplement!(Base, generateEmptyFunction, isAbstractFunction)
1376             BlackHole;
1377 }
1378
1379 unittest
1380 {
1381     // return default
1382     {
1383         interface I_1 { real test(); }
1384         auto o = new BlackHole!I_1;
1385         assert(o.test() !<>= 0); // NaN
1386     }
1387     // doc example
1388     {
1389         static class C
1390         {
1391             int m_value;
1392             this(int v) { m_value = v; }
1393             int value() @property { return m_value; }
1394
1395             abstract real realValue() @property;
1396             abstract void doSomething();
1397         }
1398
1399         auto c = new BlackHole!C(42);
1400         assert(c.value == 42);
1401
1402         assert(c.realValue !<>= 0); // NaN
1403         c.doSomething();
1404     }
1405 }
1406
1407
1408 /**
1409 $(D WhiteHole!Base) is a subclass of $(D Base) which automatically implements
1410 all abstract member functions as throw-always functions.  Each auto-implemented
1411 function fails with throwing an $(D Error) and does never return.  Useful for
1412 trapping use of not-yet-implemented functions.
1413
1414 The name came from
1415 $(WEB search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
1416 Perl module by Michael G Schwern.
1417
1418 Example:
1419 --------------------
1420 class C
1421 {
1422     abstract void notYetImplemented();
1423 }
1424
1425 void main()
1426 {
1427     auto c = new WhiteHole!C;
1428     c.notYetImplemented(); // throws an Error
1429 }
1430 --------------------
1431
1432 BUGS:
1433   Nothrow functions cause program to abort in release mode because the trap is
1434   implemented with $(D assert(0)) for nothrow functions.
1435
1436 See_Also:
1437   AutoImplement, generateAssertTrap
1438  */
1439 template WhiteHole(Base)
1440 {
1441     alias AutoImplement!(Base, generateAssertTrap, isAbstractFunction)
1442             WhiteHole;
1443 }
1444
1445 // / ditto
1446 class NotImplementedError : Error
1447 {
1448     this(string method)
1449     {
1450         super(method ~ " is not implemented");
1451     }
1452 }
1453
1454 unittest
1455 {
1456     // nothrow
1457     debug // see the BUGS above
1458     {
1459         interface I_1
1460         {
1461             void foo();
1462             void bar() nothrow;
1463         }
1464         auto o = new WhiteHole!I_1;
1465         uint trap;
1466         try { o.foo(); } catch (Error e) { ++trap; }
1467         assert(trap == 1);
1468         try { o.bar(); } catch (Error e) { ++trap; }
1469         assert(trap == 2);
1470     }
1471     // doc example
1472     {
1473         static class C
1474         {
1475             abstract void notYetImplemented();
1476         }
1477
1478         auto c = new WhiteHole!C;
1479         try
1480         {
1481             c.notYetImplemented();
1482             assert(0);
1483         }
1484         catch (Error e) {}
1485     }
1486 }
1487
1488
1489 /**
1490 $(D AutoImplement) automatically implements (by default) all abstract member
1491 functions in the class or interface $(D Base) in specified way.
1492
1493 Params:
1494   how  = template which specifies _how functions will be implemented/overridden.
1495
1496          Two arguments are passed to $(D how): the type $(D Base) and an alias
1497          to an implemented function.  Then $(D how) must return an implemented
1498          function body as a string.
1499
1500          The generated function body can use these keywords:
1501          $(UL
1502             $(LI $(D a0), $(D a1), &hellip;: arguments passed to the function;)
1503             $(LI $(D args): a tuple of the arguments;)
1504             $(LI $(D self): an alias to the function itself;)
1505             $(LI $(D parent): an alias to the overridden function (if any).)
1506          )
1507
1508         You may want to use templated property functions (instead of Implicit
1509         Template Properties) to generate complex functions:
1510 --------------------
1511 // Prints log messages for each call to overridden functions.
1512 string generateLogger(C, alias fun)() @property
1513 {
1514     enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
1515     string stmt;
1516
1517     stmt ~= q{ struct Importer { import std.stdio; } };
1518     stmt ~= `Importer.writeln$(LPAREN)"Log: ` ~ qname ~ `(", args, ")"$(RPAREN);`;
1519     static if (!__traits(isAbstractFunction, fun))
1520     {
1521         static if (is(typeof(return) == void))
1522             stmt ~= q{ parent(args); };
1523         else
1524             stmt ~= q{
1525                 auto r = parent(args);
1526                 Importer.writeln("--> ", r);
1527                 return r;
1528             };
1529     }
1530     return stmt;
1531 }
1532 --------------------
1533
1534   what = template which determines _what functions should be
1535          implemented/overridden.
1536
1537          An argument is passed to $(D what): an alias to a non-final member
1538          function in $(D Base).  Then $(D what) must return a boolean value.
1539          Return $(D true) to indicate that the passed function should be
1540          implemented/overridden.
1541
1542 --------------------
1543 // Sees if fun returns something.
1544 template hasValue(alias fun)
1545 {
1546     enum bool hasValue = !is(ReturnType!(fun) == void);
1547 }
1548 --------------------
1549
1550
1551 Note:
1552
1553 Generated code is inserted in the scope of $(D std.typecons) module.  Thus,
1554 any useful functions outside $(D std.typecons) cannot be used in the generated
1555 code.  To workaround this problem, you may $(D import) necessary things in a
1556 local struct, as done in the $(D generateLogger()) template in the above
1557 example.
1558
1559
1560 BUGS:
1561
1562 $(UL
1563  $(LI Variadic arguments to constructors are not forwarded to super.)
1564  $(LI Deep interface inheritance causes compile error with messages like
1565       "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
1566       does not override any function".  [$(BUGZILLA 2525), $(BUGZILLA 3525)] )
1567  $(LI The $(D parent) keyword is actually a delegate to the super class'
1568       corresponding member function.  [$(BUGZILLA 2540)] )
1569  $(LI Using alias template parameter in $(D how) and/or $(D what) may cause
1570      strange compile error.  Use template tuple parameter instead to workaround
1571      this problem.  [$(BUGZILLA 4217)] )
1572 )
1573  */
1574 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
1575 {
1576     private alias AutoImplement_Helper!(
1577             "autoImplement_helper_", "Base", Base, how, what )
1578              autoImplement_helper_;
1579     override mixin(autoImplement_helper_.code);
1580 }
1581
1582 /*
1583  * Code-generating stuffs are encupsulated in this helper template so that
1584  * namespace pollusion, which can cause name confliction with Base's public
1585  * members, should be minimized.
1586  */
1587 private template AutoImplement_Helper(string myName, string baseName,
1588         Base, alias generateMethodBody, alias cherrypickMethod)
1589 {
1590 private static:
1591     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1592     // Internal stuffs
1593     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1594
1595     // this would be deprecated by std.typelist.Filter
1596     template staticFilter(alias pred, lst...)
1597     {
1598         alias staticFilterImpl!(pred, lst).result staticFilter;
1599     }
1600     template staticFilterImpl(alias pred, lst...)
1601     {
1602         static if (lst.length > 0)
1603         {
1604             alias staticFilterImpl!(pred, lst[1 .. $]).result tail;
1605             //
1606             static if (true && pred!(lst[0]))
1607                 alias TypeTuple!(lst[0], tail) result;
1608             else
1609                 alias tail result;
1610         }
1611         else
1612             alias TypeTuple!() result;
1613     }
1614
1615     // Returns function overload sets in the class C, filtered with pred.
1616     template enumerateOverloads(C, alias pred)
1617     {
1618         alias enumerateOverloadsImpl!(C, pred, traits_allMembers!(C)).result
1619                 enumerateOverloads;
1620     }
1621     template enumerateOverloadsImpl(C, alias pred, names...)
1622     {
1623         static if (names.length > 0)
1624         {
1625             alias staticFilter!(pred, MemberFunctionsTuple!(C, ""~names[0])) methods;
1626             alias enumerateOverloadsImpl!(C, pred, names[1 .. $]).result next;
1627
1628             static if (methods.length > 0)
1629                 alias TypeTuple!(OverloadSet!(""~names[0], methods), next) result;
1630             else
1631                 alias next result;
1632         }
1633         else
1634             alias TypeTuple!() result;
1635     }
1636
1637
1638     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1639     // Target functions
1640     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1641
1642     // Add a non-final check to the cherrypickMethod.
1643     template canonicalPicker(fun.../+[BUG 4217]+/)
1644     {
1645         enum bool canonicalPicker = !__traits(isFinalFunction, fun[0]) &&
1646                                     cherrypickMethod!(fun);
1647     }
1648
1649     /*
1650      * A tuple of overload sets, each item of which consists of functions to be
1651      * implemented by the generated code.
1652      */
1653     alias enumerateOverloads!(Base, canonicalPicker) targetOverloadSets;
1654
1655     /*
1656      * A tuple of the super class' constructors.  Used for forwarding
1657      * constructor calls.
1658      */
1659     static if (__traits(hasMember, Base, "__ctor"))
1660         alias OverloadSet!("__ctor", __traits(getOverloads, Base, "__ctor"))
1661                 ctorOverloadSet;
1662     else
1663         alias OverloadSet!("__ctor") ctorOverloadSet; // empty
1664
1665
1666     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1667     // Type information
1668     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1669
1670     /*
1671      * The generated code will be mixed into AutoImplement, which will be
1672      * instantiated in this module's scope.  Thus, any user-defined types are
1673      * out of scope and cannot be used directly (i.e. by their names).
1674      *
1675      * We will use FuncInfo instances for accessing return types and parameter
1676      * types of the implemented functions.  The instances will be populated to
1677      * the AutoImplement's scope in a certain way; see the populate() below.
1678      */
1679
1680     // Returns the preferred identifier for the FuncInfo instance for the i-th
1681     // overloaded function with the name.
1682     template INTERNAL_FUNCINFO_ID(string name, size_t i)
1683     {
1684         enum string INTERNAL_FUNCINFO_ID = "F_" ~ name ~ "_" ~ toStringNow!(i);
1685     }
1686
1687     /*
1688      * Insert FuncInfo instances about all the target functions here.  This
1689      * enables the generated code to access type information via, for example,
1690      * "autoImplement_helper_.F_foo_1".
1691      */
1692     template populate(overloads...)
1693     {
1694         static if (overloads.length > 0)
1695         {
1696             mixin populate!(overloads[0].name, overloads[0].contents);
1697             mixin populate!(overloads[1 .. $]);
1698         }
1699     }
1700     template populate(string name, methods...)
1701     {
1702         static if (methods.length > 0)
1703         {
1704             mixin populate!(name, methods[0 .. $ - 1]);
1705             //
1706             alias methods[$ - 1] target;
1707             enum ith = methods.length - 1;
1708             mixin( "alias FuncInfo!(target) " ~
1709                         INTERNAL_FUNCINFO_ID!(name, ith) ~ ";" );
1710         }
1711     }
1712
1713     public mixin populate!(targetOverloadSets);
1714     public mixin populate!(  ctorOverloadSet );
1715
1716
1717     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1718     // Code-generating policies
1719     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1720
1721     /* Common policy configurations for generating constructors and methods. */
1722     template CommonGeneratingPolicy()
1723     {
1724         // base class identifier which generated code should use
1725         enum string BASE_CLASS_ID = baseName;
1726
1727         // FuncInfo instance identifier which generated code should use
1728         template FUNCINFO_ID(string name, size_t i)
1729         {
1730             enum string FUNCINFO_ID =
1731                 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
1732         }
1733     }
1734
1735     /* Policy configurations for generating constructors. */
1736     template ConstructorGeneratingPolicy()
1737     {
1738         mixin CommonGeneratingPolicy;
1739
1740         /* Generates constructor body.  Just forward to the base class' one. */
1741         string generateFunctionBody(ctor.../+[BUG 4217]+/)() @property
1742         {
1743             enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
1744
1745             static if (varstyle & (Variadic.C | Variadic.D))
1746             {
1747                 // the argptr-forwarding problem
1748                 pragma(msg, "Warning: AutoImplement!(", Base, ") ",
1749                         "ignored variadic arguments to the constructor ",
1750                         FunctionTypeOf!(typeof(&ctor[0])) );
1751             }
1752             return "super(args);";
1753         }
1754     }
1755
1756     /* Policy configurations for genearting target methods. */
1757     template MethodGeneratingPolicy()
1758     {
1759         mixin CommonGeneratingPolicy;
1760
1761         /* Geneartes method body. */
1762         string generateFunctionBody(func.../+[BUG 4217]+/)() @property
1763         {
1764             return generateMethodBody!(Base, func); // given
1765         }
1766     }
1767
1768
1769     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1770     // Generated code
1771     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1772
1773     alias MemberFunctionGenerator!( ConstructorGeneratingPolicy!() )
1774             ConstructorGenerator;
1775     alias MemberFunctionGenerator!( MethodGeneratingPolicy!() )
1776             MethodGenerator;
1777
1778     public enum string code =
1779         ConstructorGenerator.generateCode!(  ctorOverloadSet ) ~ "\n" ~
1780              MethodGenerator.generateCode!(targetOverloadSets);
1781
1782     debug (SHOW_GENERATED_CODE)
1783     {
1784         pragma(msg, "-------------------- < ", Base, " >");
1785         pragma(msg, code);
1786         pragma(msg, "--------------------");
1787     }
1788 }
1789
1790 //debug = SHOW_GENERATED_CODE;
1791 unittest
1792 {
1793     // no function to implement
1794     {
1795         interface I_1 {}
1796         auto o = new BlackHole!I_1;
1797     }
1798     // parameters
1799     {
1800         interface I_3 { void test(int, in int, out int, ref int, lazy int); }
1801         auto o = new BlackHole!I_3;
1802     }
1803     // use of user-defined type
1804     {
1805         struct S {}
1806         interface I_4 { S test(); }
1807         auto o = new BlackHole!I_4;
1808     }
1809     // overloads
1810     {
1811         interface I_5
1812         {
1813             void test(string);
1814             real test(real);
1815             int  test();
1816             int  test() @property; // ?
1817         }
1818         auto o = new BlackHole!I_5;
1819     }
1820     // constructor forwarding
1821     {
1822         static class C_6
1823         {
1824             this(int n) { assert(n == 42); }
1825             this(string s) { assert(s == "Deeee"); }
1826             this(...) {}
1827         }
1828         auto o1 = new BlackHole!C_6(42);
1829         auto o2 = new BlackHole!C_6("Deeee");
1830         auto o3 = new BlackHole!C_6(1, 2, 3, 4);
1831     }
1832     // attributes
1833     {
1834         interface I_7
1835         {
1836             ref int test_ref();
1837             int test_pure() pure;
1838             int test_nothrow() nothrow;
1839             int test_property() @property;
1840             int test_safe() @safe;
1841             int test_trusted() @trusted;
1842             int test_system() @system;
1843             int test_pure_nothrow() pure nothrow;
1844         }
1845         auto o = new BlackHole!I_7;
1846     }
1847     // storage classes
1848     {
1849         interface I_8
1850         {
1851             void test_const() const;
1852             void test_immutable() immutable;
1853             void test_shared() shared;
1854             void test_shared_const() shared const;
1855         }
1856         auto o = new BlackHole!I_8;
1857     }
1858     /+ // deep inheritance
1859     {
1860     // XXX [BUG 2525,3525]
1861     // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
1862         interface I { void foo(); }
1863         interface J : I {}
1864         interface K : J {}
1865         static abstract class C_9 : K {}
1866         auto o = new BlackHole!C_9;
1867     }+/
1868 }
1869
1870
1871 /*
1872 Used by MemberFunctionGenerator.
1873  */
1874 package template OverloadSet(string nam, T...)
1875 {
1876     enum string name = nam;
1877     alias T contents;
1878 }
1879
1880 /*
1881 Used by MemberFunctionGenerator.
1882  */
1883 package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func))
1884 {
1885     alias         ReturnType!(T) RT;
1886     alias ParameterTypeTuple!(T) PT;
1887 }
1888 package template FuncInfo(Func)
1889 {
1890     alias         ReturnType!(Func) RT;
1891     alias ParameterTypeTuple!(Func) PT;
1892 }
1893
1894 /*
1895 General-purpose member function generator.
1896 --------------------
1897 template GeneratingPolicy()
1898 {
1899     // [optional] the name of the class where functions are derived
1900     enum string BASE_CLASS_ID;
1901
1902     // [optional] define this if you have only function types
1903     enum bool WITHOUT_SYMBOL;
1904
1905     // [optional] Returns preferred identifier for i-th parameter.
1906     template PARAMETER_VARIABLE_ID(size_t i);
1907
1908     // Returns the identifier of the FuncInfo instance for the i-th overload
1909     // of the specified name.  The identifier must be accessible in the scope
1910     // where generated code is mixed.
1911     template FUNCINFO_ID(string name, size_t i);
1912
1913     // Returns implemented function body as a string.  When WITHOUT_SYMBOL is
1914     // defined, the latter is used.
1915     template generateFunctionBody(alias func);
1916     template generateFunctionBody(string name, FuncType);
1917 }
1918 --------------------
1919  */
1920 package template MemberFunctionGenerator(alias Policy)
1921 {
1922 private static:
1923     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1924     // Internal stuffs
1925     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1926
1927     enum CONSTRUCTOR_NAME = "__ctor";
1928
1929     // true if functions are derived from a base class
1930     enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
1931
1932     // true if functions are specified as types, not symbols
1933     enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
1934
1935     // preferred identifier for i-th parameter variable
1936     static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
1937     {
1938         alias Policy.PARAMETER_VARIABLE_ID PARAMETER_VARIABLE_ID;
1939     }
1940     else
1941     {
1942         template PARAMETER_VARIABLE_ID(size_t i)
1943         {
1944             enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i);
1945                 // default: a0, a1, ...
1946         }
1947     }
1948
1949     // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach.
1950     template CountUp(size_t n)
1951     {
1952         static if (n > 0)
1953             alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp;
1954         else
1955             alias TypeTuple!() CountUp;
1956     }
1957
1958
1959     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1960     // Code generator
1961     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
1962
1963     /*
1964      * Runs through all the target overload sets and generates D code which
1965      * implements all the functions in the overload sets.
1966      */
1967     public string generateCode(overloads...)() @property
1968     {
1969         string code = "";
1970
1971         // run through all the overload sets
1972         foreach (i_; CountUp!(0 + overloads.length)) // workaround
1973         {
1974             enum i = 0 + i_; // workaround
1975             alias overloads[i] oset;
1976
1977             code ~= generateCodeForOverloadSet!(oset);
1978
1979             static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
1980             {
1981                 // The generated function declarations may hide existing ones
1982                 // in the base class (cf. HiddenFuncError), so we put an alias
1983                 // declaration here to reveal possible hidden functions.
1984                 code ~= Format!("alias %s.%s %s;\n",
1985                             Policy.BASE_CLASS_ID, // [BUG 2540] super.
1986                             oset.name, oset.name );
1987             }
1988         }
1989         return code;
1990     }
1991
1992     // handle each overload set
1993     private string generateCodeForOverloadSet(alias oset)() @property
1994     {
1995         string code = "";
1996
1997         foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
1998         {
1999             enum i = 0 + i_; // workaround
2000             code ~= generateFunction!(
2001                     Policy.FUNCINFO_ID!(oset.name, i), oset.name,
2002                     oset.contents[i]) ~ "\n";
2003         }
2004         return code;
2005     }
2006
2007     /*
2008      * Returns D code which implements the function func.  This function
2009      * actually generates only the declarator part; the function body part is
2010      * generated by the functionGenerator() policy.
2011      */
2012     public string generateFunction(
2013             string myFuncInfo, string name, func... )() @property
2014     {
2015         enum isCtor = (name == CONSTRUCTOR_NAME);
2016
2017         string code; // the result
2018
2019         /*** Function Declarator ***/
2020         {
2021             alias FunctionTypeOf!(func) Func;
2022             alias FunctionAttribute FA;
2023             enum atts     = functionAttributes!(func);
2024             enum realName = isCtor ? "this" : name;
2025
2026             /* Made them CTFE funcs just for the sake of Format!(...) */
2027
2028             // return type with optional "ref"
2029             static string make_returnType()
2030             {
2031                 string rtype = "";
2032
2033                 if (!isCtor)
2034                 {
2035                     if (atts & FA.REF) rtype ~= "ref ";
2036                     rtype ~= myFuncInfo ~ ".RT";
2037                 }
2038                 return rtype;
2039             }
2040             enum returnType = make_returnType();
2041
2042             // function attributes attached after declaration
2043             static string make_postAtts()
2044             {
2045                 string poatts = "";
2046                 if (atts & FA.PURE    ) poatts ~= " pure";
2047                 if (atts & FA.NOTHROW ) poatts ~= " nothrow";
2048                 if (atts & FA.PROPERTY) poatts ~= " @property";
2049                 if (atts & FA.SAFE    ) poatts ~= " @safe";
2050                 if (atts & FA.TRUSTED ) poatts ~= " @trusted";
2051                 return poatts;
2052             }
2053             enum postAtts = make_postAtts();
2054
2055             // function storage class
2056             static string make_storageClass()
2057             {
2058                 string postc = "";
2059                 if (is(Func ==    shared)) postc ~= " shared";
2060                 if (is(Func ==     const)) postc ~= " const";
2061                 if (is(Func == immutable)) postc ~= " immutable";
2062                 return postc;
2063             }
2064             enum storageClass = make_storageClass();
2065
2066             //
2067             code ~= Format!("extern(%s) %s %s(%s) %s %s\n",
2068                     functionLinkage!(func),
2069                     returnType,
2070                     realName,
2071                     ""~generateParameters!(myFuncInfo, func),
2072                     postAtts, storageClass );
2073         }
2074
2075         /*** Function Body ***/
2076         code ~= "{\n";
2077         {
2078             enum nparams = ParameterTypeTuple!(func).length;
2079
2080             /* Declare keywords: args, self and parent. */
2081             string preamble;
2082
2083             preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n";
2084             if (!isCtor)
2085             {
2086                 preamble ~= "alias " ~ name ~ " self;\n";
2087                 if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func))
2088                     //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540]
2089                     preamble ~= "auto parent = &super." ~ name ~ ";\n";
2090             }
2091
2092             // Function body
2093             static if (WITHOUT_SYMBOL)
2094                 enum fbody = Policy.generateFunctionBody!(name, func);
2095             else
2096                 enum fbody = Policy.generateFunctionBody!(func);
2097
2098             code ~= preamble;
2099             code ~= fbody;
2100         }
2101         code ~= "}";
2102
2103         return code;
2104     }
2105
2106     /*
2107      * Returns D code which declares function parameters.
2108      * "ref int a0, real a1, ..."
2109      */
2110     private string generateParameters(string myFuncInfo, func...)() @property
2111     {
2112         alias ParameterStorageClass STC;
2113         alias ParameterStorageClassTuple!(func) stcs;
2114         enum nparams = stcs.length;
2115
2116         string params = ""; // the result
2117
2118         foreach (i, stc; stcs)
2119         {
2120             if (i > 0) params ~= ", ";
2121
2122             // Parameter storage classes.
2123             if (stc & STC.SCOPE) params ~= "scope ";
2124             if (stc & STC.OUT  ) params ~= "out ";
2125             if (stc & STC.REF  ) params ~= "ref ";
2126             if (stc & STC.LAZY ) params ~= "lazy ";
2127
2128             // Take parameter type from the FuncInfo.
2129             params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]";
2130
2131             // Declare a parameter variable.
2132             params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
2133         }
2134
2135         // Add some ellipsis part if needed.
2136         final switch (variadicFunctionStyle!(func))
2137         {
2138             case Variadic.NO:
2139                 break;
2140
2141             case Variadic.C, Variadic.D:
2142                 // (...) or (a, b, ...)
2143                 params ~= (nparams == 0) ? "..." : ", ...";
2144                 break;
2145
2146             case Variadic.TYPESAFE:
2147                 params ~= " ...";
2148                 break;
2149         }
2150
2151         return params;
2152     }
2153
2154     // Returns D code which enumerates n parameter variables using comma as the
2155     // separator.  "a0, a1, a2, a3"
2156     private string enumerateParameters(size_t n)() @property
2157     {
2158         string params = "";
2159
2160         foreach (i_; CountUp!(n))
2161         {
2162             enum i = 0 + i_; // workaround
2163             if (i > 0) params ~= ", ";
2164             params ~= PARAMETER_VARIABLE_ID!(i);
2165         }
2166         return params;
2167     }
2168 }
2169
2170
2171 /**
2172 Predefined how-policies for $(D AutoImplement).  These templates are used by
2173 $(D BlackHole) and $(D WhiteHole), respectively.
2174  */
2175 template generateEmptyFunction(C, func.../+[BUG 4217]+/)
2176 {
2177     static if (is(ReturnType!(func) == void))
2178         enum string generateEmptyFunction = q{
2179         };
2180     else static if (functionAttributes!(func) & FunctionAttribute.REF)
2181         enum string generateEmptyFunction = q{
2182             static typeof(return) dummy;
2183             return dummy;
2184         };
2185     else
2186         enum string generateEmptyFunction = q{
2187             return typeof(return).init;
2188         };
2189 }
2190
2191 /// ditto
2192 template generateAssertTrap(C, func.../+[BUG 4217]+/)
2193 {
2194     static if (functionAttributes!(func) & FunctionAttribute.NOTHROW) //XXX
2195     {
2196         pragma(msg, "Warning: WhiteHole!(", C, ") used assert(0) instead "
2197                 "of Error for the auto-implemented nothrow function ",
2198                 C, ".", __traits(identifier, func));
2199         enum string generateAssertTrap =
2200             `assert(0, "` ~ C.stringof ~ "." ~ __traits(identifier, func)
2201                     ~ ` is not implemented");`;
2202     }
2203     else
2204         enum string generateAssertTrap =
2205             `throw new NotImplementedError("` ~ C.stringof ~ "."
2206                     ~ __traits(identifier, func) ~ `");`;
2207 }
2208
2209 /**
2210 Options regarding auto-initialization of a $(D RefCounted) object (see
2211 the definition of $(D RefCounted) below).
2212  */
2213 enum RefCountedAutoInitialize
2214 {
2215     /// Do not auto-initialize the object
2216     no,
2217     /// Auto-initialize the object
2218     yes,
2219 }
2220
2221 /**
2222 Defines a reference-counted object containing a $(D T) value as
2223 payload. $(D RefCounted) keeps track of all references of an object,
2224 and when the reference count goes down to zero, frees the underlying
2225 store. $(D RefCounted) uses $(D malloc) and $(D free) for operation.
2226
2227 $(D RefCounted) is unsafe and should be used with care. No references
2228 to the payload should be escaped outside the $(D RefCounted) object.
2229
2230 The $(D autoInit) option makes the object ensure the store is
2231 automatically initialized. Leaving $(D autoInit ==
2232 RefCountedAutoInitialize.yes) (the default option) is convenient but
2233 has the cost of a test whenever the payload is accessed. If $(D
2234 autoInit == RefCountedAutoInitialize.no), user code must call either
2235 $(D refCountedIsInitialized) or $(D refCountedEnsureInitialized)
2236 before attempting to access the payload. Not doing so results in null
2237 pointer dereference.
2238
2239 Example:
2240 ----
2241 // A pair of an $(D int) and a $(D size_t) - the latter being the
2242 // reference count - will be dynamically allocated
2243 auto rc1 = RefCounted!int(5);
2244 assert(rc1 == 5);
2245 // No more allocation, add just one extra reference count
2246 auto rc2 = rc1;
2247 // Reference semantics
2248 rc2 = 42;
2249 assert(rc1 == 42);
2250 // the pair will be freed when rc1 and rc2 go out of scope
2251 ----
2252  */
2253 struct RefCounted(T, RefCountedAutoInitialize autoInit =
2254         RefCountedAutoInitialize.yes)
2255 if (!is(T == class))
2256 {
2257     struct _RefCounted
2258     {
2259         private Tuple!(T, "_payload", size_t, "_count") * _store;
2260         debug(RefCounted)
2261         {
2262             private bool _debugging = false;
2263             @property bool debugging() const
2264             {
2265                 return _debugging;
2266             }
2267             @property void debugging(bool d)
2268             {
2269                 if (d != _debugging)
2270                 {
2271                     writeln(typeof(this).stringof, "@",
2272                             cast(void*) _store,
2273                             d ? ": starting debug" : ": ending debug");
2274                 }
2275                 _debugging = d;
2276             }
2277         }
2278
2279         private void initialize(A...)(A args)
2280         {
2281             const sz = (*_store).sizeof;
2282             auto p = malloc(sz)[0 .. sz];
2283             if (sz >= size_t.sizeof && p.ptr)
2284             {
2285                 GC.addRange(p.ptr, sz);
2286             }
2287             emplace!T(p[0 .. T.sizeof], args);
2288             _store = cast(typeof(_store)) p.ptr;
2289             _store._count = 1;
2290             debug(RefCounted) if (debugging) writeln(typeof(this).stringof,
2291                 "@", cast(void*) _store, ": initialized with ",
2292                     A.stringof);
2293         }
2294
2295         /**
2296            Returns $(D true) if and only if the underlying store has been
2297            allocated and initialized.
2298         */
2299         @property bool isInitialized() const
2300         {
2301             return _store !is null;
2302         }
2303
2304         /**
2305            Makes sure the payload was properly initialized. Such a
2306            call is typically inserted before using the payload.
2307         */
2308         void ensureInitialized()
2309         {
2310             if (!isInitialized) initialize();
2311         }
2312
2313     }
2314     _RefCounted RefCounted;
2315
2316 /**
2317 Constructor that initializes the payload.
2318
2319 Postcondition: $(D refCountedIsInitialized)
2320  */
2321     this(A...)(A args) if (A.length > 0)
2322     {
2323         RefCounted.initialize(args);
2324     }
2325
2326 /**
2327 Constructor that tracks the reference count appropriately. If $(D
2328 !refCountedIsInitialized), does nothing.
2329  */
2330     this(this)
2331     {
2332         if (!RefCounted.isInitialized) return;
2333         ++RefCounted._store._count;
2334         debug(RefCounted) if (RefCounted.debugging)
2335                  writeln(typeof(this).stringof,
2336                 "@", cast(void*) RefCounted._store, ": bumped refcount to ",
2337                 RefCounted._store._count);
2338     }
2339
2340 /**
2341 Destructor that tracks the reference count appropriately. If $(D
2342 !refCountedIsInitialized), does nothing. When the reference count goes
2343 down to zero, calls $(D clear) agaist the payload and calls $(D free)
2344 to deallocate the corresponding resource.
2345  */
2346     ~this()
2347     {
2348         if (!RefCounted._store) return;
2349         assert(RefCounted._store._count > 0);
2350         if (--RefCounted._store._count)
2351         {
2352             debug(RefCounted) if (RefCounted.debugging)
2353                      writeln(typeof(this).stringof,
2354                     "@", cast(void*)RefCounted._store,
2355                     ": decrement refcount to ", RefCounted._store._count);
2356             return;
2357         }
2358         debug(RefCounted) if (RefCounted.debugging)
2359         {
2360             write(typeof(this).stringof,
2361                     "@", cast(void*)RefCounted._store, ": freeing... ");
2362             stdout.flush();
2363         }
2364         // Done, deallocate
2365         assert(RefCounted._store);
2366         clear(RefCounted._store._payload);
2367         if (hasIndirections!T && RefCounted._store)
2368             GC.removeRange(RefCounted._store);
2369         free(RefCounted._store);
2370         RefCounted._store = null;
2371         debug(RefCounted) if (RefCounted.debugging) writeln("done!");
2372     }
2373
2374 /**
2375 Assignment operators
2376  */
2377     void opAssign(typeof(this) rhs)
2378     {
2379         swap(RefCounted._store, rhs.RefCounted._store);
2380     }
2381
2382 /// Ditto
2383     void opAssign(T rhs)
2384     {
2385         RefCounted._store._payload = move(rhs);
2386     }
2387
2388 /**
2389 Returns a reference to the payload. If (autoInit ==
2390 RefCountedAutoInitialize.yes), calls $(D
2391 refCountedEnsureInitialized). Otherwise, just issues $(D
2392 assert(refCountedIsInitialized)).
2393  */
2394     alias refCountedPayload this;
2395
2396 /**
2397 Returns a reference to the payload. If (autoInit ==
2398 RefCountedAutoInitialize.yes), calls $(D
2399 refCountedEnsureInitialized). Otherwise, just issues $(D
2400 assert(refCountedIsInitialized)). Used with $(D alias
2401 refCountedPayload this;), so callers can just use the $(D RefCounted)
2402 object as a $(D T).
2403  */
2404     @property ref T refCountedPayload()
2405     {
2406         static if (autoInit == RefCountedAutoInitialize.yes)
2407         {
2408             RefCounted.ensureInitialized();
2409         }
2410         else
2411         {
2412             assert(RefCounted.isInitialized);
2413         }
2414         return RefCounted._store._payload;
2415     }
2416
2417 //
2418     @property ref const(T) refCountedPayload() const
2419     {
2420         static if (autoInit == RefCountedAutoInitialize.yes)
2421         {
2422             // @@@
2423             //refCountedEnsureInitialized();
2424             assert(RefCounted.isInitialized);
2425         }
2426         else
2427         {
2428             assert(RefCounted.isInitialized);
2429         }
2430         return RefCounted._store._payload;
2431     }
2432 }
2433
2434 unittest
2435 {
2436     RefCounted!int* p;
2437     {
2438         auto rc1 = RefCounted!int(5);
2439         p = &rc1;
2440         assert(rc1 == 5);
2441         assert(rc1.RefCounted._store._count == 1);
2442         auto rc2 = rc1;
2443         assert(rc1.RefCounted._store._count == 2);
2444         // Reference semantics
2445         rc2 = 42;
2446         assert(rc1 == 42);
2447         rc2 = rc2;
2448         assert(rc2.RefCounted._store._count == 2);
2449         rc1 = rc2;
2450         assert(rc1.RefCounted._store._count == 2);
2451     }
2452     assert(p.RefCounted._store == null);
2453
2454     // RefCounted as a member
2455     struct A
2456     {
2457         RefCounted!int x;
2458         this(int y)
2459         {
2460             x.RefCounted.initialize(y);
2461         }
2462         A copy()
2463         {
2464             auto another = this;
2465             return another;
2466         }
2467     }
2468     auto a = A(4);
2469     auto b = a.copy();
2470     if (a.x.RefCounted._store._count != 2) {
2471         stderr.writeln("*** BUG 4356 still unfixed");
2472     }
2473 }
2474
2475 /**
2476 Allocates a $(D class) object right inside the current scope,
2477 therefore avoiding the overhead of $(D new). This facility is unsafe;
2478 it is the responsibility of the user to not escape a reference to the
2479 object outside the scope.
2480
2481 Example:
2482 ----
2483 unittest
2484 {
2485     class A { int x; }
2486     auto a1 = scoped!A();
2487     auto a2 = scoped!A();
2488     a1.x = 42;
2489     a2.x = 53;
2490     assert(a1.x == 42);
2491 }
2492 ----
2493  */
2494 @system auto scoped(T, Args...)(Args args) if (is(T == class))
2495 {
2496     static struct Scoped
2497     {
2498         private ubyte[__traits(classInstanceSize, T)] Scoped_store = void;
2499         @property T Scoped_payload()
2500         {
2501             return cast(T) (Scoped_store.ptr);
2502         }
2503         alias Scoped_payload this;
2504
2505         @disable this(this)
2506         {
2507             writeln("Illegal call to Scoped this(this)");
2508             assert(false);
2509         }
2510
2511         ~this()
2512         {
2513             destroy(Scoped_payload);
2514             if ((cast(void**) Scoped_store.ptr)[1]) // if monitor is not null
2515             {
2516                 _d_monitordelete(Scoped_payload, true);
2517             }
2518         }
2519     }
2520
2521     byte[__traits(classInstanceSize, T)] result;
2522     static if (Args.length == 0)
2523     {
2524         result[] = typeid(T).init[];
2525         static if (is(typeof(T.init.__ctor())))
2526         {
2527             (cast(T) result.ptr).__ctor();
2528         }
2529     }
2530     else
2531     {
2532         emplace!T(cast(void[]) result, args);
2533     }
2534     return cast(Scoped) result;
2535 }
2536
2537 // Used by scoped() above
2538 private extern (C) static void _d_monitordelete(Object h, bool det);
2539
2540 /*
2541   Used by scoped() above.  Calls the destructors of an object
2542   transitively up the inheritance path, but work properly only if the
2543   static type of the object (T) is known.
2544  */
2545 private void destroy(T)(T obj) if (is(T == class))
2546 {
2547     static if (is(typeof(obj.__dtor())))
2548     {
2549         obj.__dtor();
2550     }
2551     static if (!is(T == Object) && is(T Base == super))
2552     {
2553         Base b = obj;
2554         destroy(b);
2555     }
2556 }
2557
2558 unittest
2559 {
2560     class A { int x = 1; }
2561     auto a1 = scoped!A();
2562     assert(a1.x == 1);
2563     auto a2 = scoped!A();
2564     a1.x = 42;
2565     a2.x = 53;
2566     assert(a1.x == 42);
2567 }
2568
2569 unittest
2570 {
2571     class A { int x = 1; this() { x = 2; } }
2572     auto a1 = scoped!A();
2573     assert(a1.x == 2);
2574     auto a2 = scoped!A();
2575     a1.x = 42;
2576     a2.x = 53;
2577     assert(a1.x == 42);
2578 }
2579
2580 unittest
2581 {
2582     class A { int x = 1; this(int y) { x = y; } ~this() {} }
2583     auto a1 = scoped!A(5);
2584     assert(a1.x == 5);
2585     auto a2 = scoped!A();
2586     a1.x = 42;
2587     a2.x = 53;
2588     assert(a1.x == 42);
2589 }
2590
2591 unittest
2592 {
2593     class A { static bool dead; ~this() { dead = true; } }
2594     class B : A { static bool dead; ~this() { dead = true; } }
2595     {
2596         auto b = scoped!B;
2597     }
2598     assert(B.dead, "asdasd");
2599     assert(A.dead, "asdasd");
2600 }
Note: See TracBrowser for help on using the browser.