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 module ae.utils.meta.reference; 15 16 import std.traits; 17 18 /// typeof(new T) - what we use to refer to an allocated instance 19 template RefType(T) 20 { 21 static if (is(T == class)) 22 alias T RefType; 23 else 24 alias T* RefType; 25 } 26 27 /// Reverse of RefType 28 template FromRefType(R) 29 { 30 static if (is(T == class)) 31 alias T FromRefType; 32 else 33 { 34 static assert(is(typeof(*(R.init))), R.stringof ~ " is not dereferenceable"); 35 alias typeof(*(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 template StorageType(T) 42 { 43 static if (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 pointer 47 48 // Use a struct to allow new-ing the type (you can't new a static array directly) 49 struct StorageType 50 { 51 void*[(__traits(classInstanceSize, T) + size_t.sizeof-1) / size_t.sizeof] data; 52 } 53 } 54 else 55 alias T StorageType; 56 } 57 58 // ************************************************************************ 59 60 /// Is T a reference type (a pointer or a class)? 61 template isReference(T) 62 { 63 enum isReference = isPointer!T || is(T==class); 64 } 65 66 /// Allow passing a constructed object by reference, without redundant indirection. 67 /// The intended use is with types which support the dot operator 68 /// (a non-null class, a struct, or a non-null struct pointer). 69 T* reference(T)(ref T v) 70 if (!isReference!T) 71 { 72 return &v; 73 } 74 75 /// ditto 76 T reference(T)(T v) 77 if (isReference!T) 78 { 79 return v; 80 } 81 82 /// Reverse of "reference". 83 ref typeof(*T.init) dereference(T)(T v) 84 if (!isReference!T) 85 { 86 return *v; 87 } 88 89 /// ditto 90 T dereference(T)(T v) 91 if (isReference!T) 92 { 93 return v; 94 } 95 96 unittest 97 { 98 Object o = new Object; 99 assert(o.reference is o); 100 assert(o.dereference is o); 101 102 static struct S {} 103 S s; 104 auto p = s.reference; 105 assert(p is &s); 106 assert(p.reference is p); 107 }