1 /**
2     TODO
3 
4     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
5     Authors:   Adam Búš
6 */
7 module btl.traits.common;
8 
9 import std.traits : isSomeChar, isArray;
10 
11 
12 
13 /**
14     Type used in forward constructors.
15 */
16 public struct Forward{}
17 
18 
19 
20 /**
21     same as `__traits(isRef, var)`.
22 */
23 public enum bool isRef(alias var) = __traits(isRef, var);
24 
25 
26 
27 /**
28     TODO
29 */
30 version(D_BetterC){
31     public enum bool platformSupportGC = false;
32 }
33 else{
34     public enum bool platformSupportGC = true;
35 }
36 
37 
38 
39 /**
40     TODO
41 */
42 template shouldAddGCRange(T){
43     import std.traits;
44 
45     enum shouldAddGCRange = true
46         && platformSupportGC
47         && hasIndirections!T;
48 }
49 
50 
51 
52 /**
53     remove `shared` from type `T`.
54 */
55 public alias Unshared(T) = T;
56 public alias Unshared(T: shared U, U) = U;
57 
58 
59 
60 /**
61     Same as `std.traits.hasIndirections` but for classes.
62 */
63 public template classHasIndirections(T){
64     import std.traits : hasIndirections;
65 
66     static if(is(T == class)){
67         enum bool classHasIndirections = (){
68 
69             import std.traits : BaseClassesTuple;
70             import std.meta : AliasSeq;
71 
72             bool has_indirection = false;
73 
74             static foreach (alias B; AliasSeq!(T, BaseClassesTuple!T)) {
75                 static foreach(alias Var; typeof(B.init.tupleof)){
76                     static if(hasIndirections!Var)
77                         has_indirection = true;
78                 }
79             }
80 
81             return has_indirection;
82         }();
83     }
84     else{
85         enum bool classHasIndirections = false;
86     }
87 }
88 
89 
90 //alias to `T` if `T` is class or interface, otherwise `T*`.
91 /+public template PtrOrRef(T){
92     static if(is(T == class) || is(T == interface))
93         alias PtrOrRef = T;
94     else
95         alias PtrOrRef = T*;
96 }+/
97 
98 
99 /**
100     `true` if `T` is class or interface.
101 */
102 public enum bool isClassOrInterface(T) = is(T == class) || is(T == interface);
103 
104 
105 
106 /**
107     Size of instance, if `T` is class then `__traits(classInstanceSize, T)`, otherwise `T.sizeof`
108 */
109 public template instanceSize(T){
110     static if(is(T == class))
111         enum size_t instanceSize = __traits(classInstanceSize, T);
112     else
113         enum size_t instanceSize = T.sizeof;
114 }
115 
116 
117 /*
118     [Copy, Move] ConstructableElement:
119 */
120 template isCopyConstructableElement(From, To = From){
121     enum isCopyConstructableElement = true
122         && is(typeof((ref From from){
123             To tmp = from;
124         }));
125 }
126 
127 // ditto
128 template isMoveConstructableElement(From, To = From){
129     import core.lifetime : move;
130     enum isMoveConstructableElement = true
131         && is(typeof((From from){
132             To tmp = move(from);
133         }));
134 }
135 
136 
137 
138 /*
139     [Copy, Move] AssignableElement:
140 */
141 template isCopyAssignableElement(From, To = From){
142     enum isCopyAssignableElement = true
143         && is(typeof((ref From from, ref To to){
144             to = from;
145         }));
146 }
147 
148 // ditto
149 template isMoveAssignableElement(From, To = From){
150     import core.lifetime : move;
151     enum isMoveAssignableElement = true
152         && is(typeof((From from, ref To to){
153             to = move(from);
154         }));
155 }
156 
157 
158 
159 
160