1 /**
2 * Reference type abstraction
3 *
4 * License:
5 * This Source Code Form is subject to the terms of
6 * the Mozilla Public License, v. 2.0. If a copy of
7 * the MPL was not distributed with this file, You
8 * can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * Authors:
11 * Vladimir Panteleev <vladimir@thecybershadow.net>
12 */13 14 moduleae.utils.meta.reference;
15 16 importstd.traits;
17 18 /// typeof(new T) - what we use to refer to an allocated instance19 templateRefType(T)
20 {
21 staticif (is(T == class))
22 aliasTRefType;
23 else24 aliasT* RefType;
25 }
26 27 /// Reverse of RefType28 templateFromRefType(R)
29 {
30 staticif (is(T == class))
31 aliasTFromRefType;
32 else33 {
34 staticassert(is(typeof(*(R.init))), R.stringof ~ " is not dereferenceable");
35 aliastypeof(*(R.init)) FromRefType;
36 }
37 }
38 39 /// A type that can be used to store instances of T.40 /// A struct with T's instance size if T is a class, T itself otherwise.41 templateStorageType(T)
42 {
43 staticif (is(T == class))
44 {
45 //alias void*[(__traits(classInstanceSize, T) + size_t.sizeof-1) / size_t.sizeof] StorageType;46 //static assert(__traits(classInstanceSize, T) % size_t.sizeof == 0, "TODO"); // union with a pointer47 48 // Use a struct to allow new-ing the type (you can't new a static array directly)49 structStorageType50 {
51 void*[(__traits(classInstanceSize, T) + size_t.sizeof-1) / size_t.sizeof] data;
52 }
53 }
54 else55 aliasTStorageType;
56 }
57 58 // ************************************************************************59 60 /// Is T a reference type (a pointer or a class)?61 templateisReference(T)
62 {
63 enumisReference = isPointer!T || is(T==class);
64 }
65 66 /// Allow passing a constructed (non-null class, or non-class)67 /// object by reference, without redundant indirection.68 T* reference(T)(refTv)
69 if (!isReference!T)
70 {
71 return &v;
72 }
73 74 /// ditto75 Treference(T)(Tv)
76 if (isReference!T)
77 {
78 returnv;
79 }
80 81 /// Reverse of "reference".82 reftypeof(*T.init) dereference(T)(Tv)
83 if (!isReference!T)
84 {
85 return *v;
86 }
87 88 /// ditto89 Tdereference(T)(Tv)
90 if (isReference!T)
91 {
92 returnv;
93 }
94 95 unittest96 {
97 Objecto = newObject;
98 assert(o.referenceiso);
99 assert(o.dereferenceiso);
100 101 staticstructS {}
102 Ss;
103 autop = s.reference;
104 assert(pis &s);
105 assert(p.referenceisp);
106 }