1 // Written in the D programming language.
2
3 /**
4 * Templates which extract information about types and symbols at compile time.
5 *
6 * $(SCRIPT inhibitQuickIndex = 1;)
7 *
8 * $(DIVC quickindex,
9 * $(BOOKTABLE ,
10 * $(TR $(TH Category) $(TH Templates))
11 * $(TR $(TD Symbol Name _traits) $(TD
12 * $(LREF fullyQualifiedName)
13 * $(LREF moduleName)
14 * $(LREF packageName)
15 * ))
16 * $(TR $(TD Function _traits) $(TD
17 * $(LREF isFunction)
18 * $(LREF arity)
19 * $(LREF functionAttributes)
20 * $(LREF hasFunctionAttributes)
21 * $(LREF functionLinkage)
22 * $(LREF FunctionTypeOf)
23 * $(LREF isSafe)
24 * $(LREF isUnsafe)
25 * $(LREF isFinal)
26 * $(LREF ParameterDefaults)
27 * $(LREF ParameterIdentifierTuple)
28 * $(LREF ParameterStorageClassTuple)
29 * $(LREF Parameters)
30 * $(LREF ReturnType)
31 * $(LREF SetFunctionAttributes)
32 * $(LREF variadicFunctionStyle)
33 * ))
34 * $(TR $(TD Aggregate Type _traits) $(TD
35 * $(LREF BaseClassesTuple)
36 * $(LREF BaseTypeTuple)
37 * $(LREF classInstanceAlignment)
38 * $(LREF EnumMembers)
39 * $(LREF FieldNameTuple)
40 * $(LREF Fields)
41 * $(LREF hasAliasing)
42 * $(LREF hasElaborateAssign)
43 * $(LREF hasElaborateCopyConstructor)
44 * $(LREF hasElaborateDestructor)
45 * $(LREF hasIndirections)
46 * $(LREF hasMember)
47 * $(LREF hasStaticMember)
48 * $(LREF hasNested)
49 * $(LREF hasUnsharedAliasing)
50 * $(LREF InterfacesTuple)
51 * $(LREF isInnerClass)
52 * $(LREF isNested)
53 * $(LREF MemberFunctionsTuple)
54 * $(LREF RepresentationTypeTuple)
55 * $(LREF TemplateArgsOf)
56 * $(LREF TemplateOf)
57 * $(LREF TransitiveBaseTypeTuple)
58 * ))
59 * $(TR $(TD Type Conversion) $(TD
60 * $(LREF CommonType)
61 * $(LREF ImplicitConversionTargets)
62 * $(LREF CopyTypeQualifiers)
63 * $(LREF CopyConstness)
64 * $(LREF isAssignable)
65 * $(LREF isCovariantWith)
66 * $(LREF isImplicitlyConvertible)
67 * ))
68 * $(TR $(TD SomethingTypeOf) $(TD
69 * $(LREF rvalueOf)
70 * $(LREF lvalueOf)
71 * $(LREF InoutOf)
72 * $(LREF ConstOf)
73 * $(LREF SharedOf)
74 * $(LREF SharedInoutOf)
75 * $(LREF SharedConstOf)
76 * $(LREF ImmutableOf)
77 * $(LREF QualifierOf)
78 * ))
79 * $(TR $(TD Categories of types) $(TD
80 * $(LREF allSameType)
81 * $(LREF ifTestable)
82 * $(LREF isType)
83 * $(LREF isAggregateType)
84 * $(LREF isArray)
85 * $(LREF isAssociativeArray)
86 * $(LREF isAutodecodableString)
87 * $(LREF isBasicType)
88 * $(LREF isBoolean)
89 * $(LREF isBuiltinType)
90 * $(LREF isCopyable)
91 * $(LREF isDynamicArray)
92 * $(LREF isEqualityComparable)
93 * $(LREF isFloatingPoint)
94 * $(LREF isIntegral)
95 * $(LREF isNarrowString)
96 * $(LREF isConvertibleToString)
97 * $(LREF isNumeric)
98 * $(LREF isOrderingComparable)
99 * $(LREF isPointer)
100 * $(LREF isScalarType)
101 * $(LREF isSigned)
102 * $(LREF isSIMDVector)
103 * $(LREF isSomeChar)
104 * $(LREF isSomeString)
105 * $(LREF isStaticArray)
106 * $(LREF isUnsigned)
107 * ))
108 * $(TR $(TD Type behaviours) $(TD
109 * $(LREF isAbstractClass)
110 * $(LREF isAbstractFunction)
111 * $(LREF isCallable)
112 * $(LREF isDelegate)
113 * $(LREF isExpressions)
114 * $(LREF isFinalClass)
115 * $(LREF isFinalFunction)
116 * $(LREF isFunctionPointer)
117 * $(LREF isInstanceOf)
118 * $(LREF isIterable)
119 * $(LREF isMutable)
120 * $(LREF isSomeFunction)
121 * $(LREF isTypeTuple)
122 * ))
123 * $(TR $(TD General Types) $(TD
124 * $(LREF ForeachType)
125 * $(LREF KeyType)
126 * $(LREF Largest)
127 * $(LREF mostNegative)
128 * $(LREF OriginalType)
129 * $(LREF PointerTarget)
130 * $(LREF Signed)
131 * $(LREF Unqual)
132 * $(LREF Unsigned)
133 * $(LREF ValueType)
134 * $(LREF Promoted)
135 * ))
136 * $(TR $(TD Misc) $(TD
137 * $(LREF mangledName)
138 * $(LREF Select)
139 * $(LREF select)
140 * ))
141 * $(TR $(TD User-Defined Attributes) $(TD
142 * $(LREF hasUDA)
143 * $(LREF getUDAs)
144 * $(LREF getSymbolsByUDA)
145 * ))
146 * )
147 * )
148 *
149 * Copyright: Copyright Digital Mars 2005 - 2009.
150 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
151 * Authors: $(HTTP digitalmars.com, Walter Bright),
152 * Tomasz Stachowiak ($(D isExpressions)),
153 * $(HTTP erdani.org, Andrei Alexandrescu),
154 * Shin Fujishiro,
155 * $(HTTP octarineparrot.com, Robert Clipsham),
156 * $(HTTP klickverbot.at, David Nadlinger),
157 * Kenji Hara,
158 * Shoichi Kato
159 * Source: $(PHOBOSSRC std/_traits.d)
160 */
161 /* Copyright Digital Mars 2005 - 2009.
162 * Distributed under the Boost Software License, Version 1.0.
163 * (See accompanying file LICENSE_1_0.txt or copy at
164 * http://www.boost.org/LICENSE_1_0.txt)
165 */
166 module std.traits;
167
168 import std.meta : AliasSeq, allSatisfy;
169 import std.functional : unaryFun;
170
171 // Legacy inheritance from std.typetuple
172 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797
173 import std.meta : staticMapMeta = staticMap;
174 // TODO: find a way to trigger deprecation warnings
175 //deprecated("staticMap is part of std.meta: Please import std.meta")
176 alias staticMap = staticMapMeta;
177
178 ///////////////////////////////////////////////////////////////////////////////
179 // Functions
180 ///////////////////////////////////////////////////////////////////////////////
181
182 // Petit demangler
183 // (this or similar thing will eventually go to std.demangle if necessary
184 // ctfe stuffs are available)
185 private
186 {
Demangle(T)187 struct Demangle(T)
188 {
189 T value; // extracted information
190 string rest;
191 }
192
193 /* Demangles mstr as the storage class part of Argument. */
194 Demangle!uint demangleParameterStorageClass(string mstr)
195 {
196 uint pstc = 0; // parameter storage class
197
198 // Argument --> Argument2 | M Argument2
199 if (mstr.length > 0 && mstr[0] == 'M')
200 {
201 pstc |= ParameterStorageClass.scope_;
202 mstr = mstr[1 .. $];
203 }
204
205 // Argument2 --> Type | J Type | K Type | L Type
206 ParameterStorageClass stc2;
207
208 switch (mstr.length ? mstr[0] : char.init)
209 {
210 case 'J': stc2 = ParameterStorageClass.out_; break;
211 case 'K': stc2 = ParameterStorageClass.ref_; break;
212 case 'L': stc2 = ParameterStorageClass.lazy_; break;
213 case 'N': if (mstr.length >= 2 && mstr[1] == 'k')
214 stc2 = ParameterStorageClass.return_;
215 break;
216 default : break;
217 }
218 if (stc2 != ParameterStorageClass.init)
219 {
220 pstc |= stc2;
221 mstr = mstr[1 .. $];
222 if (stc2 & ParameterStorageClass.return_)
223 mstr = mstr[1 .. $];
224 }
225
226 return Demangle!uint(pstc, mstr);
227 }
228
229 /* Demangles mstr as FuncAttrs. */
230 Demangle!uint demangleFunctionAttributes(string mstr)
231 {
232 immutable LOOKUP_ATTRIBUTE =
233 [
234 'a': FunctionAttribute.pure_,
235 'b': FunctionAttribute.nothrow_,
236 'c': FunctionAttribute.ref_,
237 'd': FunctionAttribute.property,
238 'e': FunctionAttribute.trusted,
239 'f': FunctionAttribute.safe,
240 'i': FunctionAttribute.nogc,
241 'j': FunctionAttribute.return_,
242 'l': FunctionAttribute.scope_
243 ];
244 uint atts = 0;
245
246 // FuncAttrs --> FuncAttr | FuncAttr FuncAttrs
247 // FuncAttr --> empty | Na | Nb | Nc | Nd | Ne | Nf | Ni | Nj
248 // except 'Ng' == inout, because it is a qualifier of function type
249 while (mstr.length >= 2 && mstr[0] == 'N' && mstr[1] != 'g' && mstr[1] != 'k')
250 {
251 if (FunctionAttribute att = LOOKUP_ATTRIBUTE[ mstr[1] ])
252 {
253 atts |= att;
254 mstr = mstr[2 .. $];
255 }
256 else assert(0);
257 }
258 return Demangle!uint(atts, mstr);
259 }
260
261 static if (is(ucent))
262 {
263 alias CentTypeList = AliasSeq!(cent, ucent);
264 alias SignedCentTypeList = AliasSeq!(cent);
265 alias UnsignedCentTypeList = AliasSeq!(ucent);
266 }
267 else
268 {
269 alias CentTypeList = AliasSeq!();
270 alias SignedCentTypeList = AliasSeq!();
271 alias UnsignedCentTypeList = AliasSeq!();
272 }
273
274 alias IntegralTypeList = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList);
275 alias SignedIntTypeList = AliasSeq!(byte, short, int, long, SignedCentTypeList);
276 alias UnsignedIntTypeList = AliasSeq!(ubyte, ushort, uint, ulong, UnsignedCentTypeList);
277 alias FloatingPointTypeList = AliasSeq!(float, double, real);
278 alias ImaginaryTypeList = AliasSeq!(ifloat, idouble, ireal);
279 alias ComplexTypeList = AliasSeq!(cfloat, cdouble, creal);
280 alias NumericTypeList = AliasSeq!(IntegralTypeList, FloatingPointTypeList);
281 alias CharTypeList = AliasSeq!(char, wchar, dchar);
282 }
283
284 package
285 {
286 // Add the mutable qualifier to the given type T.
MutableOf(T)287 template MutableOf(T) { alias MutableOf = T ; }
288 }
289
290 /// Add the inout qualifier to the given type T.
InoutOf(T)291 template InoutOf(T) { alias InoutOf = inout(T) ; }
292 /// Add the const qualifier to the given type T.
ConstOf(T)293 template ConstOf(T) { alias ConstOf = const(T) ; }
294 /// Add the shared qualifier to the given type T.
SharedOf(T)295 template SharedOf(T) { alias SharedOf = shared(T) ; }
296 /// Add the shared and inout qualifiers to the given type T.
SharedInoutOf(T)297 template SharedInoutOf(T) { alias SharedInoutOf = shared(inout(T)); }
298 /// Add the shared and const qualifiers to the given type T.
SharedConstOf(T)299 template SharedConstOf(T) { alias SharedConstOf = shared(const(T)); }
300 /// Add the immutable qualifier to the given type T.
ImmutableOf(T)301 template ImmutableOf(T) { alias ImmutableOf = immutable(T) ; }
302
303 @safe unittest
304 {
305 static assert(is( MutableOf!int == int));
306 static assert(is( InoutOf!int == inout int));
307 static assert(is( ConstOf!int == const int));
308 static assert(is( SharedOf!int == shared int));
309 static assert(is(SharedInoutOf!int == shared inout int));
310 static assert(is(SharedConstOf!int == shared const int));
311 static assert(is( ImmutableOf!int == immutable int));
312 }
313
314 /// Get qualifier template from the given type T
QualifierOf(T)315 template QualifierOf(T)
316 {
317 static if (is(T == shared(const U), U)) alias QualifierOf = SharedConstOf;
318 else static if (is(T == const U , U)) alias QualifierOf = ConstOf;
319 else static if (is(T == shared(inout U), U)) alias QualifierOf = SharedInoutOf;
320 else static if (is(T == inout U , U)) alias QualifierOf = InoutOf;
321 else static if (is(T == immutable U , U)) alias QualifierOf = ImmutableOf;
322 else static if (is(T == shared U , U)) alias QualifierOf = SharedOf;
323 else alias QualifierOf = MutableOf;
324 }
325
326 @safe unittest
327 {
328 alias Qual1 = QualifierOf!( int); static assert(is(Qual1!long == long));
329 alias Qual2 = QualifierOf!( inout int); static assert(is(Qual2!long == inout long));
330 alias Qual3 = QualifierOf!( const int); static assert(is(Qual3!long == const long));
331 alias Qual4 = QualifierOf!(shared int); static assert(is(Qual4!long == shared long));
332 alias Qual5 = QualifierOf!(shared inout int); static assert(is(Qual5!long == shared inout long));
333 alias Qual6 = QualifierOf!(shared const int); static assert(is(Qual6!long == shared const long));
334 alias Qual7 = QualifierOf!( immutable int); static assert(is(Qual7!long == immutable long));
335 }
336
version(unittest)337 version (unittest)
338 {
339 alias TypeQualifierList = AliasSeq!(MutableOf, ConstOf, SharedOf, SharedConstOf, ImmutableOf);
340
341 struct SubTypeOf(T)
342 {
343 T val;
344 alias val this;
345 }
346 }
347
348 private alias parentOf(alias sym) = Identity!(__traits(parent, sym));
349 private alias parentOf(alias sym : T!Args, alias T, Args...) = Identity!(__traits(parent, T));
350
351 /**
352 * Get the full package name for the given symbol.
353 */
packageName(alias T)354 template packageName(alias T)
355 {
356 import std.algorithm.searching : startsWith;
357
358 static if (__traits(compiles, parentOf!T))
359 enum parent = packageName!(parentOf!T);
360 else
361 enum string parent = null;
362
363 static if (T.stringof.startsWith("package "))
364 enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $];
365 else static if (parent)
366 enum packageName = parent;
367 else
368 static assert(false, T.stringof ~ " has no parent");
369 }
370
371 ///
372 @safe unittest
373 {
374 import std.traits;
375 static assert(packageName!packageName == "std");
376 }
377
378 @safe unittest
379 {
380 import std.array;
381
382 // Commented out because of dmd @@@BUG8922@@@
383 // static assert(packageName!std == "std"); // this package (currently: "std.std")
384 static assert(packageName!(std.traits) == "std"); // this module
385 static assert(packageName!packageName == "std"); // symbol in this module
386 static assert(packageName!(std.array) == "std"); // other module from same package
387
388 import core.sync.barrier; // local import
389 static assert(packageName!core == "core");
390 static assert(packageName!(core.sync) == "core.sync");
391 static assert(packageName!Barrier == "core.sync");
392
X12287(T)393 struct X12287(T) { T i; }
394 static assert(packageName!(X12287!int.i) == "std");
395 }
396
version(unittest)397 version (none) version (unittest) //Please uncomment me when changing packageName to test global imports
398 {
399 import core.sync.barrier; // global import
400 static assert(packageName!core == "core");
401 static assert(packageName!(core.sync) == "core.sync");
402 static assert(packageName!Barrier == "core.sync");
403 }
404
405 /**
406 * Get the module name (including package) for the given symbol.
407 */
moduleName(alias T)408 template moduleName(alias T)
409 {
410 import std.algorithm.searching : startsWith;
411
412 static assert(!T.stringof.startsWith("package "), "cannot get the module name for a package");
413
414 static if (T.stringof.startsWith("module "))
415 {
416 static if (__traits(compiles, packageName!T))
417 enum packagePrefix = packageName!T ~ '.';
418 else
419 enum packagePrefix = "";
420
421 enum moduleName = packagePrefix ~ T.stringof[7..$];
422 }
423 else
424 alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE
425 }
426
427 ///
428 @safe unittest
429 {
430 import std.traits;
431 static assert(moduleName!moduleName == "std.traits");
432 }
433
434 @safe unittest
435 {
436 import std.array;
437
438 static assert(!__traits(compiles, moduleName!std));
439 static assert(moduleName!(std.traits) == "std.traits"); // this module
440 static assert(moduleName!moduleName == "std.traits"); // symbol in this module
441 static assert(moduleName!(std.array) == "std.array"); // other module
442 static assert(moduleName!(std.array.array) == "std.array"); // symbol in other module
443
444 import core.sync.barrier; // local import
445 static assert(!__traits(compiles, moduleName!(core.sync)));
446 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
447 static assert(moduleName!Barrier == "core.sync.barrier");
448
X12287(T)449 struct X12287(T) { T i; }
450 static assert(moduleName!(X12287!int.i) == "std.traits");
451 }
452
version(unittest)453 version (none) version (unittest) //Please uncomment me when changing moduleName to test global imports
454 {
455 import core.sync.barrier; // global import
456 static assert(!__traits(compiles, moduleName!(core.sync)));
457 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
458 static assert(moduleName!Barrier == "core.sync.barrier");
459 }
460
461 /***
462 * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.
463
464 Example:
465 -----------------
466 module myModule;
467 struct MyStruct {}
468 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
469 -----------------
470 */
471 template fullyQualifiedName(T...)
472 if (T.length == 1)
473 {
474
475 static if (is(T))
476 enum fullyQualifiedName = fqnType!(T[0], false, false, false, false);
477 else
478 enum fullyQualifiedName = fqnSym!(T[0]);
479 }
480
481 ///
482 @safe unittest
483 {
484 static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
485 }
486
version(unittest)487 version (unittest)
488 {
489 // Used for both fqnType and fqnSym unittests
490 private struct QualifiedNameTests
491 {
492 struct Inner
493 {
494 }
495
496 ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 );
497 ref const(Inner[string]) retfunc( return ref Inner var1 );
498 Inner inoutFunc(inout Inner) inout;
499 shared(const(Inner[string])[]) data;
500 const Inner delegate(double, string) @safe nothrow deleg;
501 inout(int) delegate(inout int) inout inoutDeleg;
502 Inner function(out double, string) funcPtr;
503 extern(C) Inner function(double, string) cFuncPtr;
504
505 extern(C) void cVarArg(int, ...);
506 void dVarArg(...);
507 void dVarArg2(int, ...);
508 void typesafeVarArg(int[] ...);
509
510 Inner[] array;
511 Inner[16] sarray;
512 Inner[Inner] aarray;
513 const(Inner[const(Inner)]) qualAarray;
514
515 shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg;
516
517 struct Data(T) { int x; }
518 void tfunc(T...)(T args) {}
519
520 template Inst(alias A) { int x; }
521
522 class Test12309(T, int x, string s) {}
523 }
524
525 private enum QualifiedEnum
526 {
527 a = 42
528 }
529 }
530
531 private template fqnSym(alias T : X!A, alias X, A...)
532 {
fqnTuple(T...)533 template fqnTuple(T...)
534 {
535 static if (T.length == 0)
536 enum fqnTuple = "";
537 else static if (T.length == 1)
538 {
539 static if (isExpressionTuple!T)
540 enum fqnTuple = T[0].stringof;
541 else
542 enum fqnTuple = fullyQualifiedName!(T[0]);
543 }
544 else
545 enum fqnTuple = fqnTuple!(T[0]) ~ ", " ~ fqnTuple!(T[1 .. $]);
546 }
547
548 enum fqnSym =
549 fqnSym!(__traits(parent, X)) ~
550 '.' ~ __traits(identifier, X) ~ "!(" ~ fqnTuple!A ~ ")";
551 }
552
fqnSym(alias T)553 private template fqnSym(alias T)
554 {
555 static if (__traits(compiles, __traits(parent, T)) && !__traits(isSame, T, __traits(parent, T)))
556 enum parentPrefix = fqnSym!(__traits(parent, T)) ~ ".";
557 else
558 enum parentPrefix = null;
559
560 static string adjustIdent(string s)
561 {
562 import std.algorithm.searching : findSplit, skipOver;
563
564 if (s.skipOver("package ") || s.skipOver("module "))
565 return s;
566 return s.findSplit("(")[0];
567 }
568 enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
569 }
570
571 @safe unittest
572 {
573 alias fqn = fullyQualifiedName;
574
575 // Make sure those 2 are the same
576 static assert(fqnSym!fqn == fqn!fqn);
577
578 static assert(fqn!fqn == "std.traits.fullyQualifiedName");
579
580 alias qnTests = QualifiedNameTests;
581 enum prefix = "std.traits.QualifiedNameTests.";
582 static assert(fqn!(qnTests.Inner) == prefix ~ "Inner");
583 static assert(fqn!(qnTests.func) == prefix ~ "func");
584 static assert(fqn!(qnTests.Data!int) == prefix ~ "Data!(int)");
585 static assert(fqn!(qnTests.Data!int.x) == prefix ~ "Data!(int).x");
586 static assert(fqn!(qnTests.tfunc!(int[])) == prefix ~ "tfunc!(int[])");
587 static assert(fqn!(qnTests.Inst!(Object)) == prefix ~ "Inst!(object.Object)");
588 static assert(fqn!(qnTests.Inst!(Object).x) == prefix ~ "Inst!(object.Object).x");
589
590 static assert(fqn!(qnTests.Test12309!(int, 10, "str"))
591 == prefix ~ "Test12309!(int, 10, \"str\")");
592
593 import core.sync.barrier;
594 static assert(fqn!Barrier == "core.sync.barrier.Barrier");
595 }
596
597 @safe unittest
598 {
TemplatedStruct()599 struct TemplatedStruct()
600 {
601 enum foo = 0;
602 }
603 alias TemplatedStructAlias = TemplatedStruct;
604 assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo));
605 }
606
fqnType(T,bool alreadyConst,bool alreadyImmutable,bool alreadyShared,bool alreadyInout)607 private template fqnType(T,
608 bool alreadyConst, bool alreadyImmutable, bool alreadyShared, bool alreadyInout)
609 {
610 import std.format : format;
611
612 // Convenience tags
613 enum {
614 _const = 0,
615 _immutable = 1,
616 _shared = 2,
617 _inout = 3
618 }
619
620 alias qualifiers = AliasSeq!(is(T == const), is(T == immutable), is(T == shared), is(T == inout));
621 alias noQualifiers = AliasSeq!(false, false, false, false);
622
623 string storageClassesString(uint psc)() @property
624 {
625 alias PSC = ParameterStorageClass;
626
627 return format("%s%s%s%s%s",
628 psc & PSC.scope_ ? "scope " : "",
629 psc & PSC.return_ ? "return " : "",
630 psc & PSC.out_ ? "out " : "",
631 psc & PSC.ref_ ? "ref " : "",
632 psc & PSC.lazy_ ? "lazy " : ""
633 );
634 }
635
636 string parametersTypeString(T)() @property
637 {
638 alias parameters = Parameters!(T);
639 alias parameterStC = ParameterStorageClassTuple!(T);
640
641 enum variadic = variadicFunctionStyle!T;
642 static if (variadic == Variadic.no)
643 enum variadicStr = "";
644 else static if (variadic == Variadic.c)
645 enum variadicStr = ", ...";
646 else static if (variadic == Variadic.d)
647 enum variadicStr = parameters.length ? ", ..." : "...";
648 else static if (variadic == Variadic.typesafe)
649 enum variadicStr = " ...";
650 else
651 static assert(0, "New variadic style has been added, please update fullyQualifiedName implementation");
652
653 static if (parameters.length)
654 {
655 import std.algorithm.iteration : map;
656 import std.array : join;
657 import std.meta : staticMap;
658 import std.range : zip;
659
660 string result = join(
661 map!(a => format("%s%s", a[0], a[1]))(
662 zip([staticMap!(storageClassesString, parameterStC)],
663 [staticMap!(fullyQualifiedName, parameters)])
664 ),
665 ", "
666 );
667
668 return result ~= variadicStr;
669 }
670 else
671 return variadicStr;
672 }
673
674 string linkageString(T)() @property
675 {
676 enum linkage = functionLinkage!T;
677
678 if (linkage != "D")
679 return format("extern(%s) ", linkage);
680 else
681 return "";
682 }
683
684 string functionAttributeString(T)() @property
685 {
686 alias FA = FunctionAttribute;
687 enum attrs = functionAttributes!T;
688
689 static if (attrs == FA.none)
690 return "";
691 else
692 return format("%s%s%s%s%s%s%s%s",
693 attrs & FA.pure_ ? " pure" : "",
694 attrs & FA.nothrow_ ? " nothrow" : "",
695 attrs & FA.ref_ ? " ref" : "",
696 attrs & FA.property ? " @property" : "",
697 attrs & FA.trusted ? " @trusted" : "",
698 attrs & FA.safe ? " @safe" : "",
699 attrs & FA.nogc ? " @nogc" : "",
700 attrs & FA.return_ ? " return" : ""
701 );
702 }
703
704 string addQualifiers(string typeString,
705 bool addConst, bool addImmutable, bool addShared, bool addInout)
706 {
707 auto result = typeString;
708 if (addShared)
709 {
710 result = format("shared(%s)", result);
711 }
712 if (addConst || addImmutable || addInout)
713 {
714 result = format("%s(%s)",
715 addConst ? "const" :
716 addImmutable ? "immutable" : "inout",
717 result
718 );
719 }
720 return result;
721 }
722
723 // Convenience template to avoid copy-paste
724 template chain(string current)
725 {
726 enum chain = addQualifiers(current,
727 qualifiers[_const] && !alreadyConst,
728 qualifiers[_immutable] && !alreadyImmutable,
729 qualifiers[_shared] && !alreadyShared,
730 qualifiers[_inout] && !alreadyInout);
731 }
732
733 static if (is(T == string))
734 {
735 enum fqnType = "string";
736 }
737 else static if (is(T == wstring))
738 {
739 enum fqnType = "wstring";
740 }
741 else static if (is(T == dstring))
742 {
743 enum fqnType = "dstring";
744 }
745 else static if (isBasicType!T && !is(T == enum))
746 {
747 enum fqnType = chain!((Unqual!T).stringof);
748 }
749 else static if (isAggregateType!T || is(T == enum))
750 {
751 enum fqnType = chain!(fqnSym!T);
752 }
753 else static if (isStaticArray!T)
754 {
755 enum fqnType = chain!(
756 format("%s[%s]", fqnType!(typeof(T.init[0]), qualifiers), T.length)
757 );
758 }
759 else static if (isArray!T)
760 {
761 enum fqnType = chain!(
762 format("%s[]", fqnType!(typeof(T.init[0]), qualifiers))
763 );
764 }
765 else static if (isAssociativeArray!T)
766 {
767 enum fqnType = chain!(
768 format("%s[%s]", fqnType!(ValueType!T, qualifiers), fqnType!(KeyType!T, noQualifiers))
769 );
770 }
771 else static if (isSomeFunction!T)
772 {
773 static if (is(T F == delegate))
774 {
775 enum qualifierString = format("%s%s",
776 is(F == shared) ? " shared" : "",
777 is(F == inout) ? " inout" :
778 is(F == immutable) ? " immutable" :
779 is(F == const) ? " const" : ""
780 );
781 enum formatStr = "%s%s delegate(%s)%s%s";
782 enum fqnType = chain!(
783 format(formatStr, linkageString!T, fqnType!(ReturnType!T, noQualifiers),
784 parametersTypeString!(T), functionAttributeString!T, qualifierString)
785 );
786 }
787 else
788 {
789 static if (isFunctionPointer!T)
790 enum formatStr = "%s%s function(%s)%s";
791 else
792 enum formatStr = "%s%s(%s)%s";
793
794 enum fqnType = chain!(
795 format(formatStr, linkageString!T, fqnType!(ReturnType!T, noQualifiers),
796 parametersTypeString!(T), functionAttributeString!T)
797 );
798 }
799 }
800 else static if (isPointer!T)
801 {
802 enum fqnType = chain!(
803 format("%s*", fqnType!(PointerTarget!T, qualifiers))
804 );
805 }
806 else static if (is(T : __vector(V[N]), V, size_t N))
807 {
808 enum fqnType = chain!(
809 format("__vector(%s[%s])", fqnType!(V, qualifiers), N)
810 );
811 }
812 else
813 // In case something is forgotten
814 static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string");
815 }
816
817 @safe unittest
818 {
819 import std.format : format;
820 alias fqn = fullyQualifiedName;
821
822 // Verify those 2 are the same for simple case
823 alias Ambiguous = const(QualifiedNameTests.Inner);
824 static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false));
825
826 // Main tests
827 enum inner_name = "std.traits.QualifiedNameTests.Inner";
with(QualifiedNameTests)828 with (QualifiedNameTests)
829 {
830 // Special cases
831 static assert(fqn!(string) == "string");
832 static assert(fqn!(wstring) == "wstring");
833 static assert(fqn!(dstring) == "dstring");
834 static assert(fqn!(void) == "void");
835 static assert(fqn!(const(void)) == "const(void)");
836 static assert(fqn!(shared(void)) == "shared(void)");
837 static assert(fqn!(shared const(void)) == "const(shared(void))");
838 static assert(fqn!(shared inout(void)) == "inout(shared(void))");
839 static assert(fqn!(shared inout const(void)) == "const(shared(void))");
840 static assert(fqn!(inout(void)) == "inout(void)");
841 static assert(fqn!(inout const(void)) == "const(void)");
842 static assert(fqn!(immutable(void)) == "immutable(void)");
843
844 // Basic qualified name
845 static assert(fqn!(Inner) == inner_name);
846 static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type
847 static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol
848
849 // Array types
850 static assert(fqn!(typeof(array)) == format("%s[]", inner_name));
851 static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name));
852 static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name));
853
854 // qualified key for AA
855 static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name));
856
857 // Qualified composed data types
858 static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name));
859
860 // Function types + function attributes
861 static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref",
862 inner_name, inner_name));
863 static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name));
864 static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name));
865 static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name));
866 static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout");
867 static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name));
868 static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name));
869
870 // Delegate type with qualified function type
871 static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~
872 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name));
873
874 // Variable argument function types
875 static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)");
876 static assert(fqn!(typeof(dVarArg)) == "void(...)");
877 static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)");
878 static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)");
879
880 // SIMD vector
881 static if (is(__vector(float[4])))
882 {
883 static assert(fqn!(__vector(float[4])) == "__vector(float[4])");
884 }
885 }
886 }
887
888 /***
889 * Get the type of the return value from a function,
890 * a pointer to function, a delegate, a struct
891 * with an opCall, a pointer to a struct with an opCall,
892 * or a class with an $(D opCall). Please note that $(D_KEYWORD ref)
893 * is not part of a type, but the attribute of the function
894 * (see template $(LREF functionAttributes)).
895 */
896 template ReturnType(func...)
897 if (func.length == 1 && isCallable!func)
898 {
899 static if (is(FunctionTypeOf!func R == return))
900 alias ReturnType = R;
901 else
902 static assert(0, "argument has no return type");
903 }
904
905 ///
906 @safe unittest
907 {
908 int foo();
909 ReturnType!foo x; // x is declared as int
910 }
911
912 @safe unittest
913 {
914 struct G
915 {
opCallG916 int opCall (int i) { return 1;}
917 }
918
919 alias ShouldBeInt = ReturnType!G;
920 static assert(is(ShouldBeInt == int));
921
922 G g;
923 static assert(is(ReturnType!g == int));
924
925 G* p;
926 alias pg = ReturnType!p;
927 static assert(is(pg == int));
928
929 class C
930 {
opCall(int i)931 int opCall (int i) { return 1;}
932 }
933
934 static assert(is(ReturnType!C == int));
935
936 C c;
937 static assert(is(ReturnType!c == int));
938
939 class Test
940 {
prop()941 int prop() @property { return 0; }
942 }
943 alias R_Test_prop = ReturnType!(Test.prop);
944 static assert(is(R_Test_prop == int));
945
946 alias R_dglit = ReturnType!((int a) { return a; });
947 static assert(is(R_dglit == int));
948 }
949
950 /***
951 Get, as a tuple, the types of the parameters to a function, a pointer
952 to function, a delegate, a struct with an $(D opCall), a pointer to a
953 struct with an $(D opCall), or a class with an $(D opCall).
954 */
955 template Parameters(func...)
956 if (func.length == 1 && isCallable!func)
957 {
958 static if (is(FunctionTypeOf!func P == function))
959 alias Parameters = P;
960 else
961 static assert(0, "argument has no parameters");
962 }
963
964 ///
965 @safe unittest
966 {
967 int foo(int, long);
968 void bar(Parameters!foo); // declares void bar(int, long);
969 void abc(Parameters!foo[1]); // declares void abc(long);
970 }
971
972 /**
973 * Alternate name for $(LREF Parameters), kept for legacy compatibility.
974 */
975 alias ParameterTypeTuple = Parameters;
976
977 @safe unittest
978 {
foo(int i,bool b)979 int foo(int i, bool b) { return 0; }
980 static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool)));
981 static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool)));
982
opCallS983 struct S { real opCall(real r, int i) { return 0.0; } }
984 S s;
985 static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int)));
986 static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int)));
987 static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int)));
988
989 class Test
990 {
prop()991 int prop() @property { return 0; }
992 }
993 alias P_Test_prop = ParameterTypeTuple!(Test.prop);
994 static assert(P_Test_prop.length == 0);
995
996 alias P_dglit = ParameterTypeTuple!((int a){});
997 static assert(P_dglit.length == 1);
998 static assert(is(P_dglit[0] == int));
999 }
1000
1001 /**
1002 Returns the number of arguments of function $(D func).
1003 arity is undefined for variadic functions.
1004 */
1005 template arity(alias func)
1006 if ( isCallable!func && variadicFunctionStyle!func == Variadic.no )
1007 {
1008 enum size_t arity = Parameters!func.length;
1009 }
1010
1011 ///
1012 @safe unittest
1013 {
foo()1014 void foo(){}
1015 static assert(arity!foo == 0);
bar(uint)1016 void bar(uint){}
1017 static assert(arity!bar == 1);
variadicFoo(uint...)1018 void variadicFoo(uint...){}
1019 static assert(!__traits(compiles, arity!variadicFoo));
1020 }
1021
1022 /**
1023 Get tuple, one per function parameter, of the storage classes of the parameters.
1024 Params:
1025 func = function symbol or type of function, delegate, or pointer to function
1026 Returns:
1027 A tuple of ParameterStorageClass bits
1028 */
1029 enum ParameterStorageClass : uint
1030 {
1031 /**
1032 * These flags can be bitwise OR-ed together to represent complex storage
1033 * class.
1034 */
1035 none = 0,
1036 scope_ = 1, /// ditto
1037 out_ = 2, /// ditto
1038 ref_ = 4, /// ditto
1039 lazy_ = 8, /// ditto
1040 return_ = 0x10, /// ditto
1041 }
1042
1043 /// ditto
ParameterStorageClassTuple(func...)1044 template ParameterStorageClassTuple(func...)
1045 if (func.length == 1 && isCallable!func)
1046 {
1047 alias Func = FunctionTypeOf!func;
1048
1049 static if (is(Func PT == __parameters))
1050 {
1051 template StorageClass(size_t i)
1052 {
1053 static if (i < PT.length)
1054 {
1055 alias StorageClass = AliasSeq!(
1056 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)),
1057 StorageClass!(i + 1));
1058 }
1059 else
1060 alias StorageClass = AliasSeq!();
1061 }
1062 alias ParameterStorageClassTuple = StorageClass!0;
1063 }
1064 else
1065 {
1066 static assert(0, func[0].stringof ~ " is not a function");
1067 alias ParameterStorageClassTuple = AliasSeq!();
1068 }
1069 }
1070
1071 ///
1072 @safe unittest
1073 {
1074 alias STC = ParameterStorageClass; // shorten the enum name
1075
func(ref int ctx,out real result,real param)1076 void func(ref int ctx, out real result, real param)
1077 {
1078 }
1079 alias pstc = ParameterStorageClassTuple!func;
1080 static assert(pstc.length == 3); // three parameters
1081 static assert(pstc[0] == STC.ref_);
1082 static assert(pstc[1] == STC.out_);
1083 static assert(pstc[2] == STC.none);
1084 }
1085
1086 /*****************
1087 * Convert string tuple Attribs to ParameterStorageClass bits
1088 * Params:
1089 * Attribs = string tuple
1090 * Returns:
1091 * ParameterStorageClass bits
1092 */
extractParameterStorageClassFlags(Attribs...)1093 template extractParameterStorageClassFlags(Attribs...)
1094 {
1095 enum ParameterStorageClass extractParameterStorageClassFlags = ()
1096 {
1097 auto result = ParameterStorageClass.none;
1098 static if (Attribs.length > 0)
1099 {
1100 foreach (attrib; [Attribs])
1101 {
1102 final switch (attrib) with (ParameterStorageClass)
1103 {
1104 case "scope": result |= scope_; break;
1105 case "out": result |= out_; break;
1106 case "ref": result |= ref_; break;
1107 case "lazy": result |= lazy_; break;
1108 case "return": result |= return_; break;
1109 }
1110 }
1111 /* Mimic behavor of original version of ParameterStorageClassTuple()
1112 * to avoid breaking existing code.
1113 */
1114 if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
1115 result = ParameterStorageClass.return_;
1116 }
1117 return result;
1118 }();
1119 }
1120
1121 @safe unittest
1122 {
1123 alias STC = ParameterStorageClass;
1124
noparam()1125 void noparam() {}
1126 static assert(ParameterStorageClassTuple!noparam.length == 0);
1127
test(scope int *,ref int,out int,lazy int,int,return ref int i)1128 ref int test(scope int*, ref int, out int, lazy int, int, return ref int i) { return i; }
1129 alias test_pstc = ParameterStorageClassTuple!test;
1130 static assert(test_pstc.length == 6);
1131 static assert(test_pstc[0] == STC.scope_);
1132 static assert(test_pstc[1] == STC.ref_);
1133 static assert(test_pstc[2] == STC.out_);
1134 static assert(test_pstc[3] == STC.lazy_);
1135 static assert(test_pstc[4] == STC.none);
1136 static assert(test_pstc[5] == STC.return_);
1137
1138 interface Test
1139 {
1140 void test_const(int) const;
1141 void test_sharedconst(int) shared const;
1142 }
1143 Test testi;
1144
1145 alias test_const_pstc = ParameterStorageClassTuple!(Test.test_const);
1146 static assert(test_const_pstc.length == 1);
1147 static assert(test_const_pstc[0] == STC.none);
1148
1149 alias test_sharedconst_pstc = ParameterStorageClassTuple!(testi.test_sharedconst);
1150 static assert(test_sharedconst_pstc.length == 1);
1151 static assert(test_sharedconst_pstc[0] == STC.none);
1152
1153 alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {});
1154 static assert(dglit_pstc.length == 1);
1155 static assert(dglit_pstc[0] == STC.ref_);
1156
1157 // Bugzilla 9317
func(inout int param)1158 static inout(int) func(inout int param) { return param; }
1159 static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none);
1160 }
1161
1162 @safe unittest
1163 {
1164 // Bugzilla 14253
1165 static struct Foo {
1166 ref Foo opAssign(ref Foo rhs) return { return this; }
1167 }
1168
1169 alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]);
1170 }
1171
1172
1173 /**
1174 Get, as a tuple, the identifiers of the parameters to a function symbol.
1175 */
1176 template ParameterIdentifierTuple(func...)
1177 if (func.length == 1 && isCallable!func)
1178 {
1179 static if (is(FunctionTypeOf!func PT == __parameters))
1180 {
1181 template Get(size_t i)
1182 {
1183 static if (!isFunctionPointer!func && !isDelegate!func
1184 // Unnamed parameters yield CT error.
1185 && is(typeof(__traits(identifier, PT[i .. i+1]))))
1186 {
1187 enum Get = __traits(identifier, PT[i .. i+1]);
1188 }
1189 else
1190 {
1191 enum Get = "";
1192 }
1193 }
1194 }
1195 else
1196 {
1197 static assert(0, func[0].stringof ~ "is not a function");
1198
1199 // Define dummy entities to avoid pointless errors
1200 template Get(size_t i) { enum Get = ""; }
1201 alias PT = AliasSeq!();
1202 }
1203
1204 template Impl(size_t i = 0)
1205 {
1206 static if (i == PT.length)
1207 alias Impl = AliasSeq!();
1208 else
1209 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1210 }
1211
1212 alias ParameterIdentifierTuple = Impl!();
1213 }
1214
1215 ///
1216 @safe unittest
1217 {
1218 int foo(int num, string name, int);
1219 static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
1220 }
1221
1222 @safe unittest
1223 {
1224 alias PIT = ParameterIdentifierTuple;
1225
1226 void bar(int num, string name, int[] array){}
1227 static assert([PIT!bar] == ["num", "name", "array"]);
1228
1229 // might be changed in the future?
1230 void function(int num, string name) fp;
1231 static assert([PIT!fp] == ["", ""]);
1232
1233 // might be changed in the future?
1234 void delegate(int num, string name, int[long] aa) dg;
1235 static assert([PIT!dg] == ["", "", ""]);
1236
1237 interface Test
1238 {
1239 @property string getter();
1240 @property void setter(int a);
1241 Test method(int a, long b, string c);
1242 }
1243 static assert([PIT!(Test.getter)] == []);
1244 static assert([PIT!(Test.setter)] == ["a"]);
1245 static assert([PIT!(Test.method)] == ["a", "b", "c"]);
1246
1247 /+
1248 // depends on internal
1249 void baw(int, string, int[]){}
1250 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1251
1252 // depends on internal
1253 void baz(AliasSeq!(int, string, int[]) args){}
1254 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1255 +/
1256 }
1257
1258
1259 /**
1260 Get, as a tuple, the default value of the parameters to a function symbol.
1261 If a parameter doesn't have the default value, $(D void) is returned instead.
1262 */
1263 template ParameterDefaults(func...)
1264 if (func.length == 1 && isCallable!func)
1265 {
1266 alias param_names = ParameterIdentifierTuple!func;
1267 static if (is(FunctionTypeOf!(func[0]) PT == __parameters))
1268 {
1269 template Get(size_t i)
1270 {
1271 // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1272 // To avoid a name clash, generate local names that are distinct
1273 // from the parameter name, and mix them in.
1274 enum name = param_names[i];
1275 enum args = "args" ~ (name == "args" ? "_" : "");
1276 enum val = "val" ~ (name == "val" ? "_" : "");
1277 enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1278 mixin("
1279 // workaround scope escape check, see
1280 // https://issues.dlang.org/show_bug.cgi?id=16582
1281 // should use return scope once available
1282 enum get = (PT[i .. i+1] " ~ args ~ ") @trusted
1283 {
1284 // If the parameter is lazy, we force it to be evaluated
1285 // like this.
1286 auto " ~ val ~ " = " ~ args ~ "[0];
1287 auto " ~ ptr ~ " = &" ~ val ~ ";
1288 // workaround Bugzilla 16582
1289 return *" ~ ptr ~ ";
1290 };
1291 ");
1292 static if (is(typeof(get())))
1293 enum Get = get();
1294 else
1295 alias Get = void;
1296 // If default arg doesn't exist, returns void instead.
1297 }
1298 }
1299 else
1300 {
1301 static assert(0, func[0].stringof ~ "is not a function");
1302
1303 // Define dummy entities to avoid pointless errors
1304 template Get(size_t i) { enum Get = ""; }
1305 alias PT = AliasSeq!();
1306 }
1307
1308 template Impl(size_t i = 0)
1309 {
1310 static if (i == PT.length)
1311 alias Impl = AliasSeq!();
1312 else
1313 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1314 }
1315
1316 alias ParameterDefaults = Impl!();
1317 }
1318
1319 ///
1320 @safe unittest
1321 {
1322 int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
1323 static assert(is(ParameterDefaults!foo[0] == void));
1324 static assert( ParameterDefaults!foo[1] == "hello");
1325 static assert( ParameterDefaults!foo[2] == [1,2,3]);
1326 static assert( ParameterDefaults!foo[3] == 0);
1327 }
1328
1329 @safe unittest // issue 17192
1330 {
1331 static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1332 int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1333 {
1334 }
1335 alias Voids = ParameterDefaults!func;
1336 static assert(Voids.length == 12);
1337 foreach (V; Voids) static assert(is(V == void));
1338 }
1339
1340 /**
1341 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1342 */
1343 alias ParameterDefaultValueTuple = ParameterDefaults;
1344
1345 @safe unittest
1346 {
1347 alias PDVT = ParameterDefaultValueTuple;
1348
1349 void bar(int n = 1, string s = "hello"){}
1350 static assert(PDVT!bar.length == 2);
1351 static assert(PDVT!bar[0] == 1);
1352 static assert(PDVT!bar[1] == "hello");
1353 static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello"))));
1354
1355 void baz(int x, int n = 1, string s = "hello"){}
1356 static assert(PDVT!baz.length == 3);
1357 static assert(is(PDVT!baz[0] == void));
1358 static assert( PDVT!baz[1] == 1);
1359 static assert( PDVT!baz[2] == "hello");
1360 static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello"))));
1361
1362 // bug 10800 - property functions return empty string
1363 @property void foo(int x = 3) { }
1364 static assert(PDVT!foo.length == 1);
1365 static assert(PDVT!foo[0] == 3);
1366 static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3))));
1367
1368 struct Colour
1369 {
1370 ubyte a,r,g,b;
1371
1372 static immutable Colour white = Colour(255,255,255,255);
1373 }
1374 void bug8106(Colour c = Colour.white) {}
1375 //pragma(msg, PDVT!bug8106);
1376 static assert(PDVT!bug8106[0] == Colour.white);
1377 void bug16582(scope int* val = null) {}
1378 static assert(PDVT!bug16582[0] is null);
1379 }
1380
1381
1382 /**
1383 Returns the FunctionAttribute mask for function $(D func).
1384
1385 See_Also:
1386 $(LREF hasFunctionAttributes)
1387 */
1388 enum FunctionAttribute : uint
1389 {
1390 /**
1391 * These flags can be bitwise OR-ed together to represent a complex attribute.
1392 */
1393 none = 0,
1394 pure_ = 1 << 0, /// ditto
1395 nothrow_ = 1 << 1, /// ditto
1396 ref_ = 1 << 2, /// ditto
1397 property = 1 << 3, /// ditto
1398 trusted = 1 << 4, /// ditto
1399 safe = 1 << 5, /// ditto
1400 nogc = 1 << 6, /// ditto
1401 system = 1 << 7, /// ditto
1402 const_ = 1 << 8, /// ditto
1403 immutable_ = 1 << 9, /// ditto
1404 inout_ = 1 << 10, /// ditto
1405 shared_ = 1 << 11, /// ditto
1406 return_ = 1 << 12, /// ditto
1407 scope_ = 1 << 13, /// ditto
1408 }
1409
1410 /// ditto
1411 template functionAttributes(func...)
1412 if (func.length == 1 && isCallable!func)
1413 {
1414 // @bug: workaround for opCall
1415 alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
1416 func, Unqual!(FunctionTypeOf!func));
1417
1418 enum FunctionAttribute functionAttributes =
1419 extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))();
1420 }
1421
1422 ///
1423 @safe unittest
1424 {
1425 import std.traits : functionAttributes, FunctionAttribute;
1426
1427 alias FA = FunctionAttribute; // shorten the enum name
1428
1429 real func(real x) pure nothrow @safe
1430 {
1431 return x;
1432 }
1433 static assert(functionAttributes!func & FA.pure_);
1434 static assert(functionAttributes!func & FA.safe);
1435 static assert(!(functionAttributes!func & FA.trusted)); // not @trusted
1436 }
1437
1438 @system unittest
1439 {
1440 alias FA = FunctionAttribute;
1441
1442 struct S
1443 {
1444 int noF() { return 0; }
1445 int constF() const { return 0; }
1446 int immutableF() immutable { return 0; }
1447 int inoutF() inout { return 0; }
1448 int sharedF() shared { return 0; }
1449
1450 int x;
1451 ref int refF() return { return x; }
1452 int propertyF() @property { return 0; }
1453 int nothrowF() nothrow { return 0; }
1454 int nogcF() @nogc { return 0; }
1455
1456 int systemF() @system { return 0; }
1457 int trustedF() @trusted { return 0; }
1458 int safeF() @safe { return 0; }
1459
1460 int pureF() pure { return 0; }
1461 }
1462
1463 static assert(functionAttributes!(S.noF) == FA.system);
1464 static assert(functionAttributes!(typeof(S.noF)) == FA.system);
1465
1466 static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system));
1467 static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system));
1468
1469 static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system));
1470 static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system));
1471
1472 static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system));
1473 static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system));
1474
1475 static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system));
1476 static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system));
1477
1478 static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_));
1479 static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_));
1480
1481 static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system));
1482 static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system));
1483
1484 static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system));
1485 static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system));
1486
1487 static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system));
1488 static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system));
1489
1490 static assert(functionAttributes!(S.systemF) == FA.system);
1491 static assert(functionAttributes!(typeof(S.systemF)) == FA.system);
1492
1493 static assert(functionAttributes!(S.trustedF) == FA.trusted);
1494 static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted);
1495
1496 static assert(functionAttributes!(S.safeF) == FA.safe);
1497 static assert(functionAttributes!(typeof(S.safeF)) == FA.safe);
1498
1499 static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system));
1500 static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system));
1501
1502 int pure_nothrow() nothrow pure;
1503 void safe_nothrow() @safe nothrow;
1504 static ref int static_ref_property() @property;
1505 ref int ref_property() @property;
1506
1507 static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system));
1508 static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system));
1509
1510 static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_));
1511 static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_));
1512
1513 static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system));
1514 static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system));
1515
1516 static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system));
1517 static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system));
1518
1519 struct S2
1520 {
1521 int pure_const() const pure { return 0; }
1522 int pure_sharedconst() const shared pure { return 0; }
1523 }
1524
1525 static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system));
1526 static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system));
1527
1528 static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1529 static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1530
1531 static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1532 static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1533
1534 auto safeDel = delegate() @safe { };
1535 static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1536 static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1537
1538 auto trustedDel = delegate() @trusted { };
1539 static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1540 static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1541
1542 auto systemDel = delegate() @system { };
1543 static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1544 static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1545 }
1546
1547 private FunctionAttribute extractAttribFlags(Attribs...)()
1548 {
1549 auto res = FunctionAttribute.none;
1550
1551 foreach (attrib; Attribs)
1552 {
1553 switch (attrib) with (FunctionAttribute)
1554 {
1555 case "pure": res |= pure_; break;
1556 case "nothrow": res |= nothrow_; break;
1557 case "ref": res |= ref_; break;
1558 case "@property": res |= property; break;
1559 case "@trusted": res |= trusted; break;
1560 case "@safe": res |= safe; break;
1561 case "@nogc": res |= nogc; break;
1562 case "@system": res |= system; break;
1563 case "const": res |= const_; break;
1564 case "immutable": res |= immutable_; break;
1565 case "inout": res |= inout_; break;
1566 case "shared": res |= shared_; break;
1567 case "return": res |= return_; break;
1568 case "scope": res |= scope_; break;
1569 default: assert(0, attrib);
1570 }
1571 }
1572
1573 return res;
1574 }
1575
1576 /**
1577 Checks whether a function has the given attributes attached.
1578
1579 Params:
1580 args = Function to check, followed by a
1581 variadic number of function attributes as strings
1582
1583 Returns:
1584 `true`, if the function has the list of attributes attached and `false` otherwise.
1585
1586 See_Also:
1587 $(LREF functionAttributes)
1588 */
1589 template hasFunctionAttributes(args...)
1590 if (args.length > 0 && isCallable!(args[0])
1591 && allSatisfy!(isSomeString, typeof(args[1 .. $])))
1592 {
1593 enum bool hasFunctionAttributes = {
1594 import std.algorithm.searching : canFind;
1595 import std.range : only;
1596 enum funcAttribs = only(__traits(getFunctionAttributes, args[0]));
1597 foreach (attribute; args[1 .. $])
1598 {
1599 if (!funcAttribs.canFind(attribute))
1600 return false;
1601 }
1602 return true;
1603 }();
1604 }
1605
1606 ///
1607 @safe unittest
1608 {
1609 real func(real x) pure nothrow @safe;
1610 static assert(hasFunctionAttributes!(func, "@safe", "pure"));
1611 static assert(!hasFunctionAttributes!(func, "@trusted"));
1612
1613 // for templates attributes are automatically inferred
1614 bool myFunc(T)(T b)
1615 {
1616 return !b;
1617 }
1618 static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
1619 static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
1620 }
1621
1622 @system unittest
1623 {
1624 struct S
1625 {
1626 int noF();
1627 int constF() const;
1628 int immutableF() immutable;
1629 int inoutF() inout;
1630 int sharedF() shared;
1631
1632 ref int refF() return;
1633 int propertyF() @property;
1634 int nothrowF() nothrow;
1635 int nogcF() @nogc;
1636
1637 int systemF() @system;
1638 int trustedF() @trusted;
1639 int safeF() @safe;
1640
1641 int pureF() pure;
1642 }
1643
1644 // true if no args passed
1645 static assert(hasFunctionAttributes!(S.noF));
1646
1647 static assert(hasFunctionAttributes!(S.noF, "@system"));
1648 static assert(hasFunctionAttributes!(typeof(S.noF), "@system"));
1649 static assert(!hasFunctionAttributes!(S.noF, "@system", "pure"));
1650
1651 static assert(hasFunctionAttributes!(S.constF, "const", "@system"));
1652 static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system"));
1653 static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc"));
1654
1655 static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system"));
1656 static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system"));
1657 static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure"));
1658
1659 static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system"));
1660 static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system"));
1661 static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure"));
1662
1663 static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system"));
1664 static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system"));
1665 static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted"));
1666
1667 static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return"));
1668 static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return"));
1669 static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure"));
1670
1671 static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system"));
1672 static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system"));
1673 static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref"));
1674
1675 static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system"));
1676 static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system"));
1677 static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted"));
1678
1679 static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system"));
1680 static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system"));
1681 static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref"));
1682
1683 static assert(hasFunctionAttributes!(S.systemF, "@system"));
1684 static assert(hasFunctionAttributes!(typeof(S.systemF), "@system"));
1685 static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref"));
1686
1687 static assert(hasFunctionAttributes!(S.trustedF, "@trusted"));
1688 static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted"));
1689 static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe"));
1690
1691 static assert(hasFunctionAttributes!(S.safeF, "@safe"));
1692 static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe"));
1693 static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow"));
1694
1695 static assert(hasFunctionAttributes!(S.pureF, "pure", "@system"));
1696 static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system"));
1697 static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref"));
1698
1699 int pure_nothrow() nothrow pure { return 0; }
1700 void safe_nothrow() @safe nothrow { }
1701 static ref int static_ref_property() @property { return *(new int); }
1702 ref int ref_property() @property { return *(new int); }
1703
1704 static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe"));
1705 static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe"));
1706 static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted"));
1707
1708 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow"));
1709 static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow"));
1710 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure"));
1711 static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted"));
1712
1713 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe"));
1714 static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe"));
1715 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow"));
1716 static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc"));
1717
1718 static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe"));
1719 static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe"));
1720 static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc"));
1721
1722 struct S2
1723 {
1724 int pure_const() const pure { return 0; }
1725 int pure_sharedconst() const shared pure { return 0; }
1726 }
1727
1728 static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system"));
1729 static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system"));
1730 static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref"));
1731
1732 static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system"));
1733 static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system"));
1734 static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc"));
1735
1736 static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe"));
1737 static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe"));
1738 static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1739
1740 auto safeDel = delegate() @safe { };
1741 static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe"));
1742 static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe"));
1743 static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system"));
1744
1745 auto trustedDel = delegate() @trusted { };
1746 static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted"));
1747 static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted"));
1748 static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1749
1750 auto systemDel = delegate() @system { };
1751 static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system"));
1752 static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system"));
1753 static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property"));
1754
1755
1756 // call functions to make CodeCov happy
1757 {
1758 assert(pure_nothrow == 0);
1759 safe_nothrow;
1760 assert(static_ref_property == 0);
1761 assert(ref_property == 0);
1762 assert(S2().pure_const == 0);
1763 assert((shared S2()).pure_sharedconst == 0);
1764 cast(void) safeDel;
1765 cast(void) trustedDel;
1766 cast(void) systemDel;
1767 }
1768 }
1769
1770 /**
1771 $(D true) if $(D func) is $(D @safe) or $(D @trusted).
1772 */
1773 template isSafe(alias func)
1774 if (isCallable!func)
1775 {
1776 enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 ||
1777 (functionAttributes!func & FunctionAttribute.trusted) != 0;
1778 }
1779
1780 ///
1781 @safe unittest
1782 {
1783 @safe int add(int a, int b) {return a+b;}
1784 @trusted int sub(int a, int b) {return a-b;}
1785 @system int mul(int a, int b) {return a*b;}
1786
1787 static assert( isSafe!add);
1788 static assert( isSafe!sub);
1789 static assert(!isSafe!mul);
1790 }
1791
1792
1793 @safe unittest
1794 {
1795 //Member functions
1796 interface Set
1797 {
1798 int systemF() @system;
1799 int trustedF() @trusted;
1800 int safeF() @safe;
1801 }
1802 static assert( isSafe!(Set.safeF));
1803 static assert( isSafe!(Set.trustedF));
1804 static assert(!isSafe!(Set.systemF));
1805
1806 //Functions
1807 @safe static safeFunc() {}
1808 @trusted static trustedFunc() {}
1809 @system static systemFunc() {}
1810
1811 static assert( isSafe!safeFunc);
1812 static assert( isSafe!trustedFunc);
1813 static assert(!isSafe!systemFunc);
1814
1815 //Delegates
1816 auto safeDel = delegate() @safe {};
1817 auto trustedDel = delegate() @trusted {};
1818 auto systemDel = delegate() @system {};
1819
1820 static assert( isSafe!safeDel);
1821 static assert( isSafe!trustedDel);
1822 static assert(!isSafe!systemDel);
1823
1824 //Lambdas
1825 static assert( isSafe!({safeDel();}));
1826 static assert( isSafe!({trustedDel();}));
1827 static assert(!isSafe!({systemDel();}));
1828
1829 //Static opCall
1830 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
1831 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
1832 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
1833
1834 static assert( isSafe!(SafeStatic()));
1835 static assert( isSafe!(TrustedStatic()));
1836 static assert(!isSafe!(SystemStatic()));
1837
1838 //Non-static opCall
1839 struct Safe { @safe Safe opCall() { return Safe.init; } }
1840 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
1841 struct System { @system System opCall() { return System.init; } }
1842
1843 static assert( isSafe!(Safe.init()));
1844 static assert( isSafe!(Trusted.init()));
1845 static assert(!isSafe!(System.init()));
1846 }
1847
1848
1849 /**
1850 $(D true) if $(D func) is $(D @system).
1851 */
1852 template isUnsafe(alias func)
1853 {
1854 enum isUnsafe = !isSafe!func;
1855 }
1856
1857 ///
1858 @safe unittest
1859 {
1860 @safe int add(int a, int b) {return a+b;}
1861 @trusted int sub(int a, int b) {return a-b;}
1862 @system int mul(int a, int b) {return a*b;}
1863
1864 static assert(!isUnsafe!add);
1865 static assert(!isUnsafe!sub);
1866 static assert( isUnsafe!mul);
1867 }
1868
1869 @safe unittest
1870 {
1871 //Member functions
1872 interface Set
1873 {
1874 int systemF() @system;
1875 int trustedF() @trusted;
1876 int safeF() @safe;
1877 }
1878 static assert(!isUnsafe!(Set.safeF));
1879 static assert(!isUnsafe!(Set.trustedF));
1880 static assert( isUnsafe!(Set.systemF));
1881
1882 //Functions
1883 @safe static safeFunc() {}
1884 @trusted static trustedFunc() {}
1885 @system static systemFunc() {}
1886
1887 static assert(!isUnsafe!safeFunc);
1888 static assert(!isUnsafe!trustedFunc);
1889 static assert( isUnsafe!systemFunc);
1890
1891 //Delegates
1892 auto safeDel = delegate() @safe {};
1893 auto trustedDel = delegate() @trusted {};
1894 auto systemDel = delegate() @system {};
1895
1896 static assert(!isUnsafe!safeDel);
1897 static assert(!isUnsafe!trustedDel);
1898 static assert( isUnsafe!systemDel);
1899
1900 //Lambdas
1901 static assert(!isUnsafe!({safeDel();}));
1902 static assert(!isUnsafe!({trustedDel();}));
1903 static assert( isUnsafe!({systemDel();}));
1904
1905 //Static opCall
1906 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
1907 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
1908 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
1909
1910 static assert(!isUnsafe!(SafeStatic()));
1911 static assert(!isUnsafe!(TrustedStatic()));
1912 static assert( isUnsafe!(SystemStatic()));
1913
1914 //Non-static opCall
1915 struct Safe { @safe Safe opCall() { return Safe.init; } }
1916 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
1917 struct System { @system System opCall() { return System.init; } }
1918
1919 static assert(!isUnsafe!(Safe.init()));
1920 static assert(!isUnsafe!(Trusted.init()));
1921 static assert( isUnsafe!(System.init()));
1922 }
1923
1924
1925 /**
1926 Determine the linkage attribute of the function.
1927 Params:
1928 func = the function symbol, or the type of a function, delegate, or pointer to function
1929 Returns:
1930 one of the strings "D", "C", "Windows", or "Objective-C"
1931 */
1932 template functionLinkage(func...)
1933 if (func.length == 1 && isCallable!func)
1934 {
1935 enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
1936 }
1937
1938 ///
1939 @safe unittest
1940 {
1941 extern(D) void Dfunc() {}
1942 extern(C) void Cfunc() {}
1943 static assert(functionLinkage!Dfunc == "D");
1944 static assert(functionLinkage!Cfunc == "C");
1945
1946 string a = functionLinkage!Dfunc;
1947 assert(a == "D");
1948
1949 auto fp = &Cfunc;
1950 string b = functionLinkage!fp;
1951 assert(b == "C");
1952 }
1953
1954 @safe unittest
1955 {
1956 interface Test
1957 {
1958 void const_func() const;
1959 void sharedconst_func() shared const;
1960 }
1961 static assert(functionLinkage!(Test.const_func) == "D");
1962 static assert(functionLinkage!(Test.sharedconst_func) == "D");
1963
1964 static assert(functionLinkage!((int a){}) == "D");
1965 }
1966
1967
1968 /**
1969 Determines what kind of variadic parameters function has.
1970 Params:
1971 func = function symbol or type of function, delegate, or pointer to function
1972 Returns:
1973 enum Variadic
1974 */
1975 enum Variadic
1976 {
1977 no, /// Function is not variadic.
1978 c, /// Function is a _C-style variadic function, which uses
1979 /// core.stdc.stdarg
1980 /// Function is a _D-style variadic function, which uses
1981 d, /// __argptr and __arguments.
1982 typesafe, /// Function is a typesafe variadic function.
1983 }
1984
1985 /// ditto
1986 template variadicFunctionStyle(func...)
1987 if (func.length == 1 && isCallable!func)
1988 {
1989 enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
1990 enum Variadic variadicFunctionStyle =
1991 (varargs == "stdarg") ? Variadic.c :
1992 (varargs == "argptr") ? Variadic.d :
1993 (varargs == "typesafe") ? Variadic.typesafe :
1994 (varargs == "none") ? Variadic.no : Variadic.no;
1995 }
1996
1997 ///
1998 @safe unittest
1999 {
2000 void func() {}
2001 static assert(variadicFunctionStyle!func == Variadic.no);
2002
2003 extern(C) int printf(in char*, ...);
2004 static assert(variadicFunctionStyle!printf == Variadic.c);
2005 }
2006
2007 @safe unittest
2008 {
2009 import core.vararg;
2010
2011 extern(D) void novar() {}
2012 extern(C) void cstyle(int, ...) {}
2013 extern(D) void dstyle(...) {}
2014 extern(D) void typesafe(int[]...) {}
2015
2016 static assert(variadicFunctionStyle!novar == Variadic.no);
2017 static assert(variadicFunctionStyle!cstyle == Variadic.c);
2018 static assert(variadicFunctionStyle!dstyle == Variadic.d);
2019 static assert(variadicFunctionStyle!typesafe == Variadic.typesafe);
2020
2021 static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe);
2022 }
2023
2024
2025 /**
2026 Get the function type from a callable object $(D func).
2027
2028 Using builtin $(D typeof) on a property function yields the types of the
2029 property value, not of the property function itself. Still,
2030 $(D FunctionTypeOf) is able to obtain function types of properties.
2031
2032 Note:
2033 Do not confuse function types with function pointer types; function types are
2034 usually used for compile-time reflection purposes.
2035 */
2036 template FunctionTypeOf(func...)
2037 if (func.length == 1 && isCallable!func)
2038 {
2039 static if (is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function) || is(typeof(& func[0]) Fsym == delegate))
2040 {
2041 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
2042 }
2043 else static if (is(typeof(& func[0].opCall) Fobj == delegate))
2044 {
2045 alias FunctionTypeOf = Fobj; // HIT: callable object
2046 }
2047 else static if (is(typeof(& func[0].opCall) Ftyp : Ftyp*) && is(Ftyp == function))
2048 {
2049 alias FunctionTypeOf = Ftyp; // HIT: callable type
2050 }
2051 else static if (is(func[0] T) || is(typeof(func[0]) T))
2052 {
2053 static if (is(T == function))
2054 alias FunctionTypeOf = T; // HIT: function
2055 else static if (is(T Fptr : Fptr*) && is(Fptr == function))
2056 alias FunctionTypeOf = Fptr; // HIT: function pointer
2057 else static if (is(T Fdlg == delegate))
2058 alias FunctionTypeOf = Fdlg; // HIT: delegate
2059 else
2060 static assert(0);
2061 }
2062 else
2063 static assert(0);
2064 }
2065
2066 ///
2067 @safe unittest
2068 {
2069 class C
2070 {
2071 int value() @property { return 0; }
2072 }
2073 static assert(is( typeof(C.value) == int ));
2074 static assert(is( FunctionTypeOf!(C.value) == function ));
2075 }
2076
2077 @system unittest
2078 {
2079 int test(int a);
2080 int propGet() @property;
2081 int propSet(int a) @property;
2082 int function(int) test_fp;
2083 int delegate(int) test_dg;
2084 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) ));
2085 static assert(is( typeof(test) == FunctionTypeOf!test ));
2086 static assert(is( typeof(test) == FunctionTypeOf!test_fp ));
2087 static assert(is( typeof(test) == FunctionTypeOf!test_dg ));
2088 alias int GetterType() @property;
2089 alias int SetterType(int) @property;
2090 static assert(is( FunctionTypeOf!propGet == GetterType ));
2091 static assert(is( FunctionTypeOf!propSet == SetterType ));
2092
2093 interface Prop { int prop() @property; }
2094 Prop prop;
2095 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType ));
2096 static assert(is( FunctionTypeOf!(prop.prop) == GetterType ));
2097
2098 class Callable { int opCall(int) { return 0; } }
2099 auto call = new Callable;
2100 static assert(is( FunctionTypeOf!call == typeof(test) ));
2101
2102 struct StaticCallable { static int opCall(int) { return 0; } }
2103 StaticCallable stcall_val;
2104 StaticCallable* stcall_ptr;
2105 static assert(is( FunctionTypeOf!stcall_val == typeof(test) ));
2106 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) ));
2107
2108 interface Overloads
2109 {
2110 void test(string);
2111 real test(real);
2112 int test(int);
2113 int test() @property;
2114 }
2115 alias ov = AliasSeq!(__traits(getVirtualFunctions, Overloads, "test"));
2116 alias F_ov0 = FunctionTypeOf!(ov[0]);
2117 alias F_ov1 = FunctionTypeOf!(ov[1]);
2118 alias F_ov2 = FunctionTypeOf!(ov[2]);
2119 alias F_ov3 = FunctionTypeOf!(ov[3]);
2120 static assert(is(F_ov0* == void function(string)));
2121 static assert(is(F_ov1* == real function(real)));
2122 static assert(is(F_ov2* == int function(int)));
2123 static assert(is(F_ov3* == int function() @property));
2124
2125 alias F_dglit = FunctionTypeOf!((int a){ return a; });
2126 static assert(is(F_dglit* : int function(int)));
2127 }
2128
2129 /**
2130 * Constructs a new function or delegate type with the same basic signature
2131 * as the given one, but different attributes (including linkage).
2132 *
2133 * This is especially useful for adding/removing attributes to/from types in
2134 * generic code, where the actual type name cannot be spelt out.
2135 *
2136 * Params:
2137 * T = The base type.
2138 * linkage = The desired linkage of the result type.
2139 * attrs = The desired $(LREF FunctionAttribute)s of the result type.
2140 */
2141 template SetFunctionAttributes(T, string linkage, uint attrs)
2142 if (isFunctionPointer!T || isDelegate!T)
2143 {
2144 mixin({
2145 import std.algorithm.searching : canFind;
2146
2147 static assert(!(attrs & FunctionAttribute.trusted) ||
2148 !(attrs & FunctionAttribute.safe),
2149 "Cannot have a function/delegate that is both trusted and safe.");
2150
2151 static immutable linkages = ["D", "C", "Windows", "C++", "System"];
2152 static assert(canFind(linkages, linkage), "Invalid linkage '" ~
2153 linkage ~ "', must be one of " ~ linkages.stringof ~ ".");
2154
2155 string result = "alias ";
2156
2157 static if (linkage != "D")
2158 result ~= "extern(" ~ linkage ~ ") ";
2159
2160 static if (attrs & FunctionAttribute.ref_)
2161 result ~= "ref ";
2162
2163 result ~= "ReturnType!T";
2164
2165 static if (isDelegate!T)
2166 result ~= " delegate";
2167 else
2168 result ~= " function";
2169
2170 result ~= "(";
2171
2172 static if (Parameters!T.length > 0)
2173 result ~= "Parameters!T";
2174
2175 enum varStyle = variadicFunctionStyle!T;
2176 static if (varStyle == Variadic.c)
2177 result ~= ", ...";
2178 else static if (varStyle == Variadic.d)
2179 result ~= "...";
2180 else static if (varStyle == Variadic.typesafe)
2181 result ~= "...";
2182
2183 result ~= ")";
2184
2185 static if (attrs & FunctionAttribute.pure_)
2186 result ~= " pure";
2187 static if (attrs & FunctionAttribute.nothrow_)
2188 result ~= " nothrow";
2189 static if (attrs & FunctionAttribute.property)
2190 result ~= " @property";
2191 static if (attrs & FunctionAttribute.trusted)
2192 result ~= " @trusted";
2193 static if (attrs & FunctionAttribute.safe)
2194 result ~= " @safe";
2195 static if (attrs & FunctionAttribute.nogc)
2196 result ~= " @nogc";
2197 static if (attrs & FunctionAttribute.system)
2198 result ~= " @system";
2199 static if (attrs & FunctionAttribute.const_)
2200 result ~= " const";
2201 static if (attrs & FunctionAttribute.immutable_)
2202 result ~= " immutable";
2203 static if (attrs & FunctionAttribute.inout_)
2204 result ~= " inout";
2205 static if (attrs & FunctionAttribute.shared_)
2206 result ~= " shared";
2207 static if (attrs & FunctionAttribute.return_)
2208 result ~= " return";
2209
2210 result ~= " SetFunctionAttributes;";
2211 return result;
2212 }());
2213 }
2214
2215 /// Ditto
2216 template SetFunctionAttributes(T, string linkage, uint attrs)
2217 if (is(T == function))
2218 {
2219 // To avoid a lot of syntactic headaches, we just use the above version to
2220 // operate on the corresponding function pointer type and then remove the
2221 // indirection again.
2222 alias SetFunctionAttributes = FunctionTypeOf!(SetFunctionAttributes!(T*, linkage, attrs));
2223 }
2224
2225 ///
2226 @safe unittest
2227 {
2228 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
2229
2230 auto assumePure(T)(T t)
2231 if (isFunctionPointer!T || isDelegate!T)
2232 {
2233 enum attrs = functionAttributes!T | FunctionAttribute.pure_;
2234 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
2235 }
2236 }
2237
2238 version (unittest)
2239 {
2240 // Some function types to test.
2241 int sc(scope int, ref int, out int, lazy int, int);
2242 extern(System) int novar();
2243 extern(C) int cstyle(int, ...);
2244 extern(D) int dstyle(...);
2245 extern(D) int typesafe(int[]...);
2246 }
2247 @safe unittest
2248 {
2249 import std.algorithm.iteration : reduce;
2250
2251 alias FA = FunctionAttribute;
2252 foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle),
2253 typeof(&dstyle), typeof(&typesafe)))
2254 {
2255 foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT))
2256 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
2257 enum linkage = functionLinkage!T;
2258 enum attrs = functionAttributes!T;
2259
2260 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T),
2261 "Identity check failed for: " ~ T.stringof);
2262
2263 // Check that all linkage types work (D-style variadics require D linkage).
2264 static if (variadicFunctionStyle!T != Variadic.d)
2265 {
2266 foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++"))
2267 {
2268 alias New = SetFunctionAttributes!(T, newLinkage, attrs);
2269 static assert(functionLinkage!New == newLinkage,
2270 "Linkage test failed for: " ~ T.stringof ~ ", " ~ newLinkage ~
2271 " (got " ~ New.stringof ~ ")");
2272 }
2273 }
2274
2275 // Add @safe.
2276 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe);
2277 static assert(functionAttributes!T1 == FA.safe);
2278
2279 // Add all known attributes, excluding conflicting ones.
2280 enum allAttrs = reduce!"a | b"([EnumMembers!FA])
2281 & ~FA.safe & ~FA.property & ~FA.const_ & ~FA.immutable_ & ~FA.inout_
2282 & ~FA.shared_ & ~FA.system & ~FA.return_ & ~FA.scope_;
2283
2284 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs);
2285 static assert(functionAttributes!T2 == allAttrs);
2286
2287 // Strip all attributes again.
2288 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none);
2289 static assert(is(T3 == T));
2290 }();
2291 }
2292 }
2293
2294
2295 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2296 // Aggregate Types
2297 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2298
2299 /**
2300 Determines whether `T` is a class nested inside another class
2301 and that `T.outer` is the implicit reference to the outer class
2302 (i.e. `outer` has not been used as a field or method name)
2303
2304 Params:
2305 T = type to test
2306
2307 Returns:
2308 `true` if `T` is a class nested inside another, with the conditions described above;
2309 `false` otherwise
2310 */
2311 template isInnerClass(T)
2312 if (is(T == class))
2313 {
2314 import std.meta : staticIndexOf;
2315
2316 static if (is(typeof(T.outer)))
2317 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T))
2318 && (staticIndexOf!(__traits(allMembers, T), "outer") == -1);
2319 else
2320 enum isInnerClass = false;
2321 }
2322
2323 ///
2324 @safe unittest
2325 {
2326 class C
2327 {
2328 int outer;
2329 }
2330 static assert(!isInnerClass!C);
2331
2332 class Outer1
2333 {
2334 class Inner1 { }
2335 class Inner2
2336 {
2337 int outer;
2338 }
2339 }
2340 static assert(isInnerClass!(Outer1.Inner1));
2341 static assert(!isInnerClass!(Outer1.Inner2));
2342
2343 static class Outer2
2344 {
2345 static class Inner
2346 {
2347 int outer;
2348 }
2349 }
2350 static assert(!isInnerClass!(Outer2.Inner));
2351 }
2352
2353 /**
2354 Determines whether $(D T) has its own context pointer.
2355 $(D T) must be either $(D class), $(D struct), or $(D union).
2356 */
2357 template isNested(T)
2358 if (is(T == class) || is(T == struct) || is(T == union))
2359 {
2360 enum isNested = __traits(isNested, T);
2361 }
2362
2363 ///
2364 @safe unittest
2365 {
2366 static struct S { }
2367 static assert(!isNested!S);
2368
2369 int i;
2370 struct NestedStruct { void f() { ++i; } }
2371 static assert(isNested!NestedStruct);
2372 }
2373
2374 /**
2375 Determines whether $(D T) or any of its representation types
2376 have a context pointer.
2377 */
2378 template hasNested(T)
2379 {
2380 import std.meta : anySatisfy, Filter;
2381
2382 static if (isStaticArray!T && T.length)
2383 enum hasNested = hasNested!(typeof(T.init[0]));
2384 else static if (is(T == class) || is(T == struct) || is(T == union))
2385 {
2386 // prevent infinite recursion for class with member of same type
2387 enum notSame(U) = !is(Unqual!T == Unqual!U);
2388 enum hasNested = isNested!T ||
2389 anySatisfy!(.hasNested, Filter!(notSame, Fields!T));
2390 }
2391 else
2392 enum hasNested = false;
2393 }
2394
2395 ///
2396 @safe unittest
2397 {
2398 static struct S { }
2399
2400 int i;
2401 struct NS { void f() { ++i; } }
2402
2403 static assert(!hasNested!(S[2]));
2404 static assert(hasNested!(NS[2]));
2405 }
2406
2407 @safe unittest
2408 {
2409 static assert(!__traits(compiles, isNested!int));
2410 static assert(!hasNested!int);
2411
2412 static struct StaticStruct { }
2413 static assert(!isNested!StaticStruct);
2414 static assert(!hasNested!StaticStruct);
2415
2416 int i;
2417 struct NestedStruct { void f() { ++i; } }
2418 static assert( isNested!NestedStruct);
2419 static assert( hasNested!NestedStruct);
2420 static assert( isNested!(immutable NestedStruct));
2421 static assert( hasNested!(immutable NestedStruct));
2422
2423 static assert(!__traits(compiles, isNested!(NestedStruct[1])));
2424 static assert( hasNested!(NestedStruct[1]));
2425 static assert(!hasNested!(NestedStruct[0]));
2426
2427 struct S1 { NestedStruct nested; }
2428 static assert(!isNested!S1);
2429 static assert( hasNested!S1);
2430
2431 static struct S2 { NestedStruct nested; }
2432 static assert(!isNested!S2);
2433 static assert( hasNested!S2);
2434
2435 static struct S3 { NestedStruct[0] nested; }
2436 static assert(!isNested!S3);
2437 static assert(!hasNested!S3);
2438
2439 static union U { NestedStruct nested; }
2440 static assert(!isNested!U);
2441 static assert( hasNested!U);
2442
2443 static class StaticClass { }
2444 static assert(!isNested!StaticClass);
2445 static assert(!hasNested!StaticClass);
2446
2447 class NestedClass { void f() { ++i; } }
2448 static assert( isNested!NestedClass);
2449 static assert( hasNested!NestedClass);
2450 static assert( isNested!(immutable NestedClass));
2451 static assert( hasNested!(immutable NestedClass));
2452
2453 static assert(!__traits(compiles, isNested!(NestedClass[1])));
2454 static assert( hasNested!(NestedClass[1]));
2455 static assert(!hasNested!(NestedClass[0]));
2456
2457 static class A
2458 {
2459 A a;
2460 }
2461 static assert(!hasNested!A);
2462 }
2463
2464
2465 /***
2466 * Get as a tuple the types of the fields of a struct, class, or union.
2467 * This consists of the fields that take up memory space,
2468 * excluding the hidden fields like the virtual function
2469 * table pointer or a context pointer for nested types.
2470 * If $(D T) isn't a struct, class, or union returns a tuple
2471 * with one element $(D T).
2472 */
2473 template Fields(T)
2474 {
2475 static if (is(T == struct) || is(T == union))
2476 alias Fields = typeof(T.tupleof[0 .. $ - isNested!T]);
2477 else static if (is(T == class))
2478 alias Fields = typeof(T.tupleof);
2479 else
2480 alias Fields = AliasSeq!T;
2481 }
2482
2483 ///
2484 @safe unittest
2485 {
2486 struct S { int x; float y; }
2487 static assert(is(Fields!S == AliasSeq!(int, float)));
2488 }
2489
2490 /**
2491 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2492 */
2493 alias FieldTypeTuple = Fields;
2494
2495 @safe unittest
2496 {
2497 static assert(is(FieldTypeTuple!int == AliasSeq!int));
2498
2499 static struct StaticStruct1 { }
2500 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!()));
2501
2502 static struct StaticStruct2 { int a, b; }
2503 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int)));
2504
2505 int i;
2506
2507 struct NestedStruct1 { void f() { ++i; } }
2508 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!()));
2509
2510 struct NestedStruct2 { int a; void f() { ++i; } }
2511 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int));
2512
2513 class NestedClass { int a; void f() { ++i; } }
2514 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int));
2515 }
2516
2517
2518 //Required for FieldNameTuple
2519 private enum NameOf(alias T) = T.stringof;
2520
2521 /**
2522 * Get as an expression tuple the names of the fields of a struct, class, or
2523 * union. This consists of the fields that take up memory space, excluding the
2524 * hidden fields like the virtual function table pointer or a context pointer
2525 * for nested types. If $(D T) isn't a struct, class, or union returns an
2526 * expression tuple with an empty string.
2527 */
2528 template FieldNameTuple(T)
2529 {
2530 import std.meta : staticMap;
2531 static if (is(T == struct) || is(T == union))
2532 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]);
2533 else static if (is(T == class))
2534 alias FieldNameTuple = staticMap!(NameOf, T.tupleof);
2535 else
2536 alias FieldNameTuple = AliasSeq!"";
2537 }
2538
2539 ///
2540 @safe unittest
2541 {
2542 struct S { int x; float y; }
2543 static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
2544 static assert(FieldNameTuple!int == AliasSeq!"");
2545 }
2546
2547 @safe unittest
2548 {
2549 static assert(FieldNameTuple!int == AliasSeq!"");
2550
2551 static struct StaticStruct1 { }
2552 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!()));
2553
2554 static struct StaticStruct2 { int a, b; }
2555 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b"));
2556
2557 int i;
2558
2559 struct NestedStruct1 { void f() { ++i; } }
2560 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!()));
2561
2562 struct NestedStruct2 { int a; void f() { ++i; } }
2563 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a");
2564
2565 class NestedClass { int a; void f() { ++i; } }
2566 static assert(FieldNameTuple!NestedClass == AliasSeq!"a");
2567 }
2568
2569
2570 /***
2571 Get the primitive types of the fields of a struct or class, in
2572 topological order.
2573 */
2574 template RepresentationTypeTuple(T)
2575 {
2576 template Impl(T...)
2577 {
2578 static if (T.length == 0)
2579 {
2580 alias Impl = AliasSeq!();
2581 }
2582 else
2583 {
2584 import std.typecons : Rebindable;
2585
2586 static if (is(T[0] R: Rebindable!R))
2587 {
2588 alias Impl = Impl!(Impl!R, T[1 .. $]);
2589 }
2590 else static if (is(T[0] == struct) || is(T[0] == union))
2591 {
2592 // @@@BUG@@@ this should work
2593 //alias .RepresentationTypes!(T[0].tupleof)
2594 // RepresentationTypes;
2595 alias Impl = Impl!(FieldTypeTuple!(T[0]), T[1 .. $]);
2596 }
2597 else
2598 {
2599 alias Impl = AliasSeq!(T[0], Impl!(T[1 .. $]));
2600 }
2601 }
2602 }
2603
2604 static if (is(T == struct) || is(T == union) || is(T == class))
2605 {
2606 alias RepresentationTypeTuple = Impl!(FieldTypeTuple!T);
2607 }
2608 else
2609 {
2610 alias RepresentationTypeTuple = Impl!T;
2611 }
2612 }
2613
2614 ///
2615 @safe unittest
2616 {
2617 struct S1 { int a; float b; }
2618 struct S2 { char[] a; union { S1 b; S1 * c; } }
2619 alias R = RepresentationTypeTuple!S2;
2620 assert(R.length == 4
2621 && is(R[0] == char[]) && is(R[1] == int)
2622 && is(R[2] == float) && is(R[3] == S1*));
2623 }
2624
2625 @safe unittest
2626 {
2627 alias S1 = RepresentationTypeTuple!int;
2628 static assert(is(S1 == AliasSeq!int));
2629
2630 struct S2 { int a; }
2631 struct S3 { int a; char b; }
2632 struct S4 { S1 a; int b; S3 c; }
2633 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int));
2634 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char)));
2635 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char)));
2636
2637 struct S11 { int a; float b; }
2638 struct S21 { char[] a; union { S11 b; S11 * c; } }
2639 alias R = RepresentationTypeTuple!S21;
2640 assert(R.length == 4
2641 && is(R[0] == char[]) && is(R[1] == int)
2642 && is(R[2] == float) && is(R[3] == S11*));
2643
2644 class C { int a; float b; }
2645 alias R1 = RepresentationTypeTuple!C;
2646 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float));
2647
2648 /* Issue 6642 */
2649 import std.typecons : Rebindable;
2650
2651 struct S5 { int a; Rebindable!(immutable Object) b; }
2652 alias R2 = RepresentationTypeTuple!S5;
2653 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
2654 }
2655
2656 /*
2657 Statically evaluates to $(D true) if and only if $(D T)'s
2658 representation contains at least one field of pointer or array type.
2659 Members of class types are not considered raw pointers. Pointers to
2660 immutable objects are not considered raw aliasing.
2661 */
2662 private template hasRawAliasing(T...)
2663 {
2664 template Impl(T...)
2665 {
2666 static if (T.length == 0)
2667 {
2668 enum Impl = false;
2669 }
2670 else
2671 {
2672 static if (is(T[0] foo : U*, U) && !isFunctionPointer!(T[0]))
2673 enum has = !is(U == immutable);
2674 else static if (is(T[0] foo : U[], U) && !isStaticArray!(T[0]))
2675 enum has = !is(U == immutable);
2676 else static if (isAssociativeArray!(T[0]))
2677 enum has = !is(T[0] == immutable);
2678 else
2679 enum has = false;
2680
2681 enum Impl = has || Impl!(T[1 .. $]);
2682 }
2683 }
2684
2685 enum hasRawAliasing = Impl!(RepresentationTypeTuple!T);
2686 }
2687
2688 ///
2689 @safe unittest
2690 {
2691 // simple types
2692 static assert(!hasRawAliasing!int);
2693 static assert( hasRawAliasing!(char*));
2694 // references aren't raw pointers
2695 static assert(!hasRawAliasing!Object);
2696 // built-in arrays do contain raw pointers
2697 static assert( hasRawAliasing!(int[]));
2698 // aggregate of simple types
2699 struct S1 { int a; double b; }
2700 static assert(!hasRawAliasing!S1);
2701 // indirect aggregation
2702 struct S2 { S1 a; double b; }
2703 static assert(!hasRawAliasing!S2);
2704 }
2705
2706 @safe unittest
2707 {
2708 // struct with a pointer member
2709 struct S3 { int a; double * b; }
2710 static assert( hasRawAliasing!S3);
2711 // struct with an indirect pointer member
2712 struct S4 { S3 a; double b; }
2713 static assert( hasRawAliasing!S4);
2714 struct S5 { int a; Object z; int c; }
2715 static assert( hasRawAliasing!S3);
2716 static assert( hasRawAliasing!S4);
2717 static assert(!hasRawAliasing!S5);
2718
2719 union S6 { int a; int b; }
2720 union S7 { int a; int * b; }
2721 static assert(!hasRawAliasing!S6);
2722 static assert( hasRawAliasing!S7);
2723
2724 static assert(!hasRawAliasing!(void delegate()));
2725 static assert(!hasRawAliasing!(void delegate() const));
2726 static assert(!hasRawAliasing!(void delegate() immutable));
2727 static assert(!hasRawAliasing!(void delegate() shared));
2728 static assert(!hasRawAliasing!(void delegate() shared const));
2729 static assert(!hasRawAliasing!(const(void delegate())));
2730 static assert(!hasRawAliasing!(immutable(void delegate())));
2731
2732 struct S8 { void delegate() a; int b; Object c; }
2733 class S12 { typeof(S8.tupleof) a; }
2734 class S13 { typeof(S8.tupleof) a; int* b; }
2735 static assert(!hasRawAliasing!S8);
2736 static assert(!hasRawAliasing!S12);
2737 static assert( hasRawAliasing!S13);
2738
2739 enum S9 { a }
2740 static assert(!hasRawAliasing!S9);
2741
2742 // indirect members
2743 struct S10 { S7 a; int b; }
2744 struct S11 { S6 a; int b; }
2745 static assert( hasRawAliasing!S10);
2746 static assert(!hasRawAliasing!S11);
2747
2748 static assert( hasRawAliasing!(int[string]));
2749 static assert(!hasRawAliasing!(immutable(int[string])));
2750 }
2751
2752 /*
2753 Statically evaluates to $(D true) if and only if $(D T)'s
2754 representation contains at least one non-shared field of pointer or
2755 array type. Members of class types are not considered raw pointers.
2756 Pointers to immutable objects are not considered raw aliasing.
2757 */
2758 private template hasRawUnsharedAliasing(T...)
2759 {
2760 template Impl(T...)
2761 {
2762 static if (T.length == 0)
2763 {
2764 enum Impl = false;
2765 }
2766 else
2767 {
2768 static if (is(T[0] foo : U*, U) && !isFunctionPointer!(T[0]))
2769 enum has = !is(U == immutable) && !is(U == shared);
2770 else static if (is(T[0] foo : U[], U) && !isStaticArray!(T[0]))
2771 enum has = !is(U == immutable) && !is(U == shared);
2772 else static if (isAssociativeArray!(T[0]))
2773 enum has = !is(T[0] == immutable) && !is(T[0] == shared);
2774 else
2775 enum has = false;
2776
2777 enum Impl = has || Impl!(T[1 .. $]);
2778 }
2779 }
2780
2781 enum hasRawUnsharedAliasing = Impl!(RepresentationTypeTuple!T);
2782 }
2783
2784 ///
2785 @safe unittest
2786 {
2787 // simple types
2788 static assert(!hasRawUnsharedAliasing!int);
2789 static assert( hasRawUnsharedAliasing!(char*));
2790 static assert(!hasRawUnsharedAliasing!(shared char*));
2791 // references aren't raw pointers
2792 static assert(!hasRawUnsharedAliasing!Object);
2793 // built-in arrays do contain raw pointers
2794 static assert( hasRawUnsharedAliasing!(int[]));
2795 static assert(!hasRawUnsharedAliasing!(shared int[]));
2796 // aggregate of simple types
2797 struct S1 { int a; double b; }
2798 static assert(!hasRawUnsharedAliasing!S1);
2799 // indirect aggregation
2800 struct S2 { S1 a; double b; }
2801 static assert(!hasRawUnsharedAliasing!S2);
2802 // struct with a pointer member
2803 struct S3 { int a; double * b; }
2804 static assert( hasRawUnsharedAliasing!S3);
2805 struct S4 { int a; shared double * b; }
2806 static assert(!hasRawUnsharedAliasing!S4);
2807 }
2808
2809 @safe unittest
2810 {
2811 // struct with a pointer member
2812 struct S3 { int a; double * b; }
2813 static assert( hasRawUnsharedAliasing!S3);
2814 struct S4 { int a; shared double * b; }
2815 static assert(!hasRawUnsharedAliasing!S4);
2816 // struct with an indirect pointer member
2817 struct S5 { S3 a; double b; }
2818 static assert( hasRawUnsharedAliasing!S5);
2819 struct S6 { S4 a; double b; }
2820 static assert(!hasRawUnsharedAliasing!S6);
2821 struct S7 { int a; Object z; int c; }
2822 static assert( hasRawUnsharedAliasing!S5);
2823 static assert(!hasRawUnsharedAliasing!S6);
2824 static assert(!hasRawUnsharedAliasing!S7);
2825
2826 union S8 { int a; int b; }
2827 union S9 { int a; int* b; }
2828 union S10 { int a; shared int* b; }
2829 static assert(!hasRawUnsharedAliasing!S8);
2830 static assert( hasRawUnsharedAliasing!S9);
2831 static assert(!hasRawUnsharedAliasing!S10);
2832
2833 static assert(!hasRawUnsharedAliasing!(void delegate()));
2834 static assert(!hasRawUnsharedAliasing!(void delegate() const));
2835 static assert(!hasRawUnsharedAliasing!(void delegate() immutable));
2836 static assert(!hasRawUnsharedAliasing!(void delegate() shared));
2837 static assert(!hasRawUnsharedAliasing!(void delegate() shared const));
2838 static assert(!hasRawUnsharedAliasing!(const(void delegate())));
2839 static assert(!hasRawUnsharedAliasing!(const(void delegate() const)));
2840 static assert(!hasRawUnsharedAliasing!(const(void delegate() immutable)));
2841 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared)));
2842 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared const)));
2843 static assert(!hasRawUnsharedAliasing!(immutable(void delegate())));
2844 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() const)));
2845 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() immutable)));
2846 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared)));
2847 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared const)));
2848 static assert(!hasRawUnsharedAliasing!(shared(void delegate())));
2849 static assert(!hasRawUnsharedAliasing!(shared(void delegate() const)));
2850 static assert(!hasRawUnsharedAliasing!(shared(void delegate() immutable)));
2851 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared)));
2852 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared const)));
2853 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate()))));
2854 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() const))));
2855 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() immutable))));
2856 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared))));
2857 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared const))));
2858 static assert(!hasRawUnsharedAliasing!(void function()));
2859
2860 enum S13 { a }
2861 static assert(!hasRawUnsharedAliasing!S13);
2862
2863 // indirect members
2864 struct S14 { S9 a; int b; }
2865 struct S15 { S10 a; int b; }
2866 struct S16 { S6 a; int b; }
2867 static assert( hasRawUnsharedAliasing!S14);
2868 static assert(!hasRawUnsharedAliasing!S15);
2869 static assert(!hasRawUnsharedAliasing!S16);
2870
2871 static assert( hasRawUnsharedAliasing!(int[string]));
2872 static assert(!hasRawUnsharedAliasing!(shared(int[string])));
2873 static assert(!hasRawUnsharedAliasing!(immutable(int[string])));
2874
2875 struct S17
2876 {
2877 void delegate() shared a;
2878 void delegate() immutable b;
2879 void delegate() shared const c;
2880 shared(void delegate()) d;
2881 shared(void delegate() shared) e;
2882 shared(void delegate() immutable) f;
2883 shared(void delegate() shared const) g;
2884 immutable(void delegate()) h;
2885 immutable(void delegate() shared) i;
2886 immutable(void delegate() immutable) j;
2887 immutable(void delegate() shared const) k;
2888 shared(const(void delegate())) l;
2889 shared(const(void delegate() shared)) m;
2890 shared(const(void delegate() immutable)) n;
2891 shared(const(void delegate() shared const)) o;
2892 }
2893 struct S18 { typeof(S17.tupleof) a; void delegate() p; }
2894 struct S19 { typeof(S17.tupleof) a; Object p; }
2895 struct S20 { typeof(S17.tupleof) a; int* p; }
2896 class S21 { typeof(S17.tupleof) a; }
2897 class S22 { typeof(S17.tupleof) a; void delegate() p; }
2898 class S23 { typeof(S17.tupleof) a; Object p; }
2899 class S24 { typeof(S17.tupleof) a; int* p; }
2900 static assert(!hasRawUnsharedAliasing!S17);
2901 static assert(!hasRawUnsharedAliasing!(immutable(S17)));
2902 static assert(!hasRawUnsharedAliasing!(shared(S17)));
2903 static assert(!hasRawUnsharedAliasing!S18);
2904 static assert(!hasRawUnsharedAliasing!(immutable(S18)));
2905 static assert(!hasRawUnsharedAliasing!(shared(S18)));
2906 static assert(!hasRawUnsharedAliasing!S19);
2907 static assert(!hasRawUnsharedAliasing!(immutable(S19)));
2908 static assert(!hasRawUnsharedAliasing!(shared(S19)));
2909 static assert( hasRawUnsharedAliasing!S20);
2910 static assert(!hasRawUnsharedAliasing!(immutable(S20)));
2911 static assert(!hasRawUnsharedAliasing!(shared(S20)));
2912 static assert(!hasRawUnsharedAliasing!S21);
2913 static assert(!hasRawUnsharedAliasing!(immutable(S21)));
2914 static assert(!hasRawUnsharedAliasing!(shared(S21)));
2915 static assert(!hasRawUnsharedAliasing!S22);
2916 static assert(!hasRawUnsharedAliasing!(immutable(S22)));
2917 static assert(!hasRawUnsharedAliasing!(shared(S22)));
2918 static assert(!hasRawUnsharedAliasing!S23);
2919 static assert(!hasRawUnsharedAliasing!(immutable(S23)));
2920 static assert(!hasRawUnsharedAliasing!(shared(S23)));
2921 static assert( hasRawUnsharedAliasing!S24);
2922 static assert(!hasRawUnsharedAliasing!(immutable(S24)));
2923 static assert(!hasRawUnsharedAliasing!(shared(S24)));
2924 struct S25 {}
2925 class S26 {}
2926 interface S27 {}
2927 union S28 {}
2928 static assert(!hasRawUnsharedAliasing!S25);
2929 static assert(!hasRawUnsharedAliasing!S26);
2930 static assert(!hasRawUnsharedAliasing!S27);
2931 static assert(!hasRawUnsharedAliasing!S28);
2932 }
2933
2934 /*
2935 Statically evaluates to $(D true) if and only if $(D T)'s
2936 representation includes at least one non-immutable object reference.
2937 */
2938
2939 private template hasObjects(T...)
2940 {
2941 static if (T.length == 0)
2942 {
2943 enum hasObjects = false;
2944 }
2945 else static if (is(T[0] == struct))
2946 {
2947 enum hasObjects = hasObjects!(
2948 RepresentationTypeTuple!(T[0]), T[1 .. $]);
2949 }
2950 else
2951 {
2952 enum hasObjects = ((is(T[0] == class) || is(T[0] == interface))
2953 && !is(T[0] == immutable)) || hasObjects!(T[1 .. $]);
2954 }
2955 }
2956
2957 /*
2958 Statically evaluates to $(D true) if and only if $(D T)'s
2959 representation includes at least one non-immutable non-shared object
2960 reference.
2961 */
2962 private template hasUnsharedObjects(T...)
2963 {
2964 static if (T.length == 0)
2965 {
2966 enum hasUnsharedObjects = false;
2967 }
2968 else static if (is(T[0] == struct))
2969 {
2970 enum hasUnsharedObjects = hasUnsharedObjects!(
2971 RepresentationTypeTuple!(T[0]), T[1 .. $]);
2972 }
2973 else
2974 {
2975 enum hasUnsharedObjects = ((is(T[0] == class) || is(T[0] == interface)) &&
2976 !is(T[0] == immutable) && !is(T[0] == shared)) ||
2977 hasUnsharedObjects!(T[1 .. $]);
2978 }
2979 }
2980
2981 /**
2982 Returns $(D true) if and only if $(D T)'s representation includes at
2983 least one of the following: $(OL $(LI a raw pointer $(D U*) and $(D U)
2984 is not immutable;) $(LI an array $(D U[]) and $(D U) is not
2985 immutable;) $(LI a reference to a class or interface type $(D C) and $(D C) is
2986 not immutable.) $(LI an associative array that is not immutable.)
2987 $(LI a delegate.))
2988 */
2989 template hasAliasing(T...)
2990 {
2991 import std.meta : anySatisfy;
2992 import std.typecons : Rebindable;
2993
2994 static if (T.length && is(T[0] : Rebindable!R, R))
2995 {
2996 enum hasAliasing = hasAliasing!(R, T[1 .. $]);
2997 }
2998 else
2999 {
3000 template isAliasingDelegate(T)
3001 {
3002 enum isAliasingDelegate = isDelegate!T
3003 && !is(T == immutable)
3004 && !is(FunctionTypeOf!T == immutable);
3005 }
3006 enum hasAliasing = hasRawAliasing!T || hasObjects!T ||
3007 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T);
3008 }
3009 }
3010
3011 ///
3012 @safe unittest
3013 {
3014 struct S1 { int a; Object b; }
3015 struct S2 { string a; }
3016 struct S3 { int a; immutable Object b; }
3017 struct S4 { float[3] vals; }
3018 static assert( hasAliasing!S1);
3019 static assert(!hasAliasing!S2);
3020 static assert(!hasAliasing!S3);
3021 static assert(!hasAliasing!S4);
3022 }
3023
3024 @safe unittest
3025 {
3026 static assert( hasAliasing!(uint[uint]));
3027 static assert(!hasAliasing!(immutable(uint[uint])));
3028 static assert( hasAliasing!(void delegate()));
3029 static assert( hasAliasing!(void delegate() const));
3030 static assert(!hasAliasing!(void delegate() immutable));
3031 static assert( hasAliasing!(void delegate() shared));
3032 static assert( hasAliasing!(void delegate() shared const));
3033 static assert( hasAliasing!(const(void delegate())));
3034 static assert( hasAliasing!(const(void delegate() const)));
3035 static assert(!hasAliasing!(const(void delegate() immutable)));
3036 static assert( hasAliasing!(const(void delegate() shared)));
3037 static assert( hasAliasing!(const(void delegate() shared const)));
3038 static assert(!hasAliasing!(immutable(void delegate())));
3039 static assert(!hasAliasing!(immutable(void delegate() const)));
3040 static assert(!hasAliasing!(immutable(void delegate() immutable)));
3041 static assert(!hasAliasing!(immutable(void delegate() shared)));
3042 static assert(!hasAliasing!(immutable(void delegate() shared const)));
3043 static assert( hasAliasing!(shared(const(void delegate()))));
3044 static assert( hasAliasing!(shared(const(void delegate() const))));
3045 static assert(!hasAliasing!(shared(const(void delegate() immutable))));
3046 static assert( hasAliasing!(shared(const(void delegate() shared))));
3047 static assert( hasAliasing!(shared(const(void delegate() shared const))));
3048 static assert(!hasAliasing!(void function()));
3049
3050 interface I;
3051 static assert( hasAliasing!I);
3052
3053 import std.typecons : Rebindable;
3054 static assert( hasAliasing!(Rebindable!(const Object)));
3055 static assert(!hasAliasing!(Rebindable!(immutable Object)));
3056 static assert( hasAliasing!(Rebindable!(shared Object)));
3057 static assert( hasAliasing!(Rebindable!Object));
3058
3059 struct S5
3060 {
3061 void delegate() immutable b;
3062 shared(void delegate() immutable) f;
3063 immutable(void delegate() immutable) j;
3064 shared(const(void delegate() immutable)) n;
3065 }
3066 struct S6 { typeof(S5.tupleof) a; void delegate() p; }
3067 static assert(!hasAliasing!S5);
3068 static assert( hasAliasing!S6);
3069
3070 struct S7 { void delegate() a; int b; Object c; }
3071 class S8 { int a; int b; }
3072 class S9 { typeof(S8.tupleof) a; }
3073 class S10 { typeof(S8.tupleof) a; int* b; }
3074 static assert( hasAliasing!S7);
3075 static assert( hasAliasing!S8);
3076 static assert( hasAliasing!S9);
3077 static assert( hasAliasing!S10);
3078 struct S11 {}
3079 class S12 {}
3080 interface S13 {}
3081 union S14 {}
3082 static assert(!hasAliasing!S11);
3083 static assert( hasAliasing!S12);
3084 static assert( hasAliasing!S13);
3085 static assert(!hasAliasing!S14);
3086 }
3087 /**
3088 Returns $(D true) if and only if $(D T)'s representation includes at
3089 least one of the following: $(OL $(LI a raw pointer $(D U*);) $(LI an
3090 array $(D U[]);) $(LI a reference to a class type $(D C).)
3091 $(LI an associative array.) $(LI a delegate.))
3092 */
3093 template hasIndirections(T)
3094 {
3095 import std.meta : anySatisfy;
3096 static if (is(T == struct) || is(T == union))
3097 enum hasIndirections = anySatisfy!(.hasIndirections, FieldTypeTuple!T);
3098 else static if (isStaticArray!T && is(T : E[N], E, size_t N))
3099 enum hasIndirections = is(E == void) ? true : hasIndirections!E;
3100 else static if (isFunctionPointer!T)
3101 enum hasIndirections = false;
3102 else
3103 enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T ||
3104 isAssociativeArray!T || is (T == class) || is(T == interface);
3105 }
3106
3107 ///
3108 @safe unittest
3109 {
3110 static assert( hasIndirections!(int[string]));
3111 static assert( hasIndirections!(void delegate()));
3112 static assert( hasIndirections!(void delegate() immutable));
3113 static assert( hasIndirections!(immutable(void delegate())));
3114 static assert( hasIndirections!(immutable(void delegate() immutable)));
3115
3116 static assert(!hasIndirections!(void function()));
3117 static assert( hasIndirections!(void*[1]));
3118 static assert(!hasIndirections!(byte[1]));
3119 }
3120
3121 @safe unittest
3122 {
3123 // void static array hides actual type of bits, so "may have indirections".
3124 static assert( hasIndirections!(void[1]));
3125 interface I {}
3126 struct S1 {}
3127 struct S2 { int a; }
3128 struct S3 { int a; int b; }
3129 struct S4 { int a; int* b; }
3130 struct S5 { int a; Object b; }
3131 struct S6 { int a; string b; }
3132 struct S7 { int a; immutable Object b; }
3133 struct S8 { int a; immutable I b; }
3134 struct S9 { int a; void delegate() b; }
3135 struct S10 { int a; immutable(void delegate()) b; }
3136 struct S11 { int a; void delegate() immutable b; }
3137 struct S12 { int a; immutable(void delegate() immutable) b; }
3138 class S13 {}
3139 class S14 { int a; }
3140 class S15 { int a; int b; }
3141 class S16 { int a; Object b; }
3142 class S17 { string a; }
3143 class S18 { int a; immutable Object b; }
3144 class S19 { int a; immutable(void delegate() immutable) b; }
3145 union S20 {}
3146 union S21 { int a; }
3147 union S22 { int a; int b; }
3148 union S23 { int a; Object b; }
3149 union S24 { string a; }
3150 union S25 { int a; immutable Object b; }
3151 union S26 { int a; immutable(void delegate() immutable) b; }
3152 static assert( hasIndirections!I);
3153 static assert(!hasIndirections!S1);
3154 static assert(!hasIndirections!S2);
3155 static assert(!hasIndirections!S3);
3156 static assert( hasIndirections!S4);
3157 static assert( hasIndirections!S5);
3158 static assert( hasIndirections!S6);
3159 static assert( hasIndirections!S7);
3160 static assert( hasIndirections!S8);
3161 static assert( hasIndirections!S9);
3162 static assert( hasIndirections!S10);
3163 static assert( hasIndirections!S12);
3164 static assert( hasIndirections!S13);
3165 static assert( hasIndirections!S14);
3166 static assert( hasIndirections!S15);
3167 static assert( hasIndirections!S16);
3168 static assert( hasIndirections!S17);
3169 static assert( hasIndirections!S18);
3170 static assert( hasIndirections!S19);
3171 static assert(!hasIndirections!S20);
3172 static assert(!hasIndirections!S21);
3173 static assert(!hasIndirections!S22);
3174 static assert( hasIndirections!S23);
3175 static assert( hasIndirections!S24);
3176 static assert( hasIndirections!S25);
3177 static assert( hasIndirections!S26);
3178 }
3179
3180 @safe unittest //12000
3181 {
3182 static struct S(T)
3183 {
3184 static assert(hasIndirections!T);
3185 }
3186
3187 static class A(T)
3188 {
3189 S!A a;
3190 }
3191
3192 A!int dummy;
3193 }
3194
3195 /**
3196 Returns $(D true) if and only if $(D T)'s representation includes at
3197 least one of the following: $(OL $(LI a raw pointer $(D U*) and $(D U)
3198 is not immutable or shared;) $(LI an array $(D U[]) and $(D U) is not
3199 immutable or shared;) $(LI a reference to a class type $(D C) and
3200 $(D C) is not immutable or shared.) $(LI an associative array that is not
3201 immutable or shared.) $(LI a delegate that is not shared.))
3202 */
3203
3204 template hasUnsharedAliasing(T...)
3205 {
3206 import std.meta : anySatisfy;
3207 import std.typecons : Rebindable;
3208
3209 static if (!T.length)
3210 {
3211 enum hasUnsharedAliasing = false;
3212 }
3213 else static if (is(T[0] R: Rebindable!R))
3214 {
3215 enum hasUnsharedAliasing = hasUnsharedAliasing!R;
3216 }
3217 else
3218 {
3219 template unsharedDelegate(T)
3220 {
3221 enum bool unsharedDelegate = isDelegate!T
3222 && !is(T == shared)
3223 && !is(T == shared)
3224 && !is(T == immutable)
3225 && !is(FunctionTypeOf!T == shared)
3226 && !is(FunctionTypeOf!T == immutable);
3227 }
3228
3229 enum hasUnsharedAliasing =
3230 hasRawUnsharedAliasing!(T[0]) ||
3231 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!(T[0])) ||
3232 hasUnsharedObjects!(T[0]) ||
3233 hasUnsharedAliasing!(T[1..$]);
3234 }
3235 }
3236
3237 ///
3238 @safe unittest
3239 {
3240 struct S1 { int a; Object b; }
3241 struct S2 { string a; }
3242 struct S3 { int a; immutable Object b; }
3243 static assert( hasUnsharedAliasing!S1);
3244 static assert(!hasUnsharedAliasing!S2);
3245 static assert(!hasUnsharedAliasing!S3);
3246
3247 struct S4 { int a; shared Object b; }
3248 struct S5 { char[] a; }
3249 struct S6 { shared char[] b; }
3250 struct S7 { float[3] vals; }
3251 static assert(!hasUnsharedAliasing!S4);
3252 static assert( hasUnsharedAliasing!S5);
3253 static assert(!hasUnsharedAliasing!S6);
3254 static assert(!hasUnsharedAliasing!S7);
3255 }
3256
3257 @safe unittest
3258 {
3259 /* Issue 6642 */
3260 import std.typecons : Rebindable;
3261 struct S8 { int a; Rebindable!(immutable Object) b; }
3262 static assert(!hasUnsharedAliasing!S8);
3263
3264 static assert( hasUnsharedAliasing!(uint[uint]));
3265
3266 static assert( hasUnsharedAliasing!(void delegate()));
3267 static assert( hasUnsharedAliasing!(void delegate() const));
3268 static assert(!hasUnsharedAliasing!(void delegate() immutable));
3269 static assert(!hasUnsharedAliasing!(void delegate() shared));
3270 static assert(!hasUnsharedAliasing!(void delegate() shared const));
3271 }
3272
3273 @safe unittest
3274 {
3275 import std.typecons : Rebindable;
3276 static assert( hasUnsharedAliasing!(const(void delegate())));
3277 static assert( hasUnsharedAliasing!(const(void delegate() const)));
3278 static assert(!hasUnsharedAliasing!(const(void delegate() immutable)));
3279 static assert(!hasUnsharedAliasing!(const(void delegate() shared)));
3280 static assert(!hasUnsharedAliasing!(const(void delegate() shared const)));
3281 static assert(!hasUnsharedAliasing!(immutable(void delegate())));
3282 static assert(!hasUnsharedAliasing!(immutable(void delegate() const)));
3283 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable)));
3284 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared)));
3285 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const)));
3286 static assert(!hasUnsharedAliasing!(shared(void delegate())));
3287 static assert(!hasUnsharedAliasing!(shared(void delegate() const)));
3288 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable)));
3289 static assert(!hasUnsharedAliasing!(shared(void delegate() shared)));
3290 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const)));
3291 static assert(!hasUnsharedAliasing!(shared(const(void delegate()))));
3292 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const))));
3293 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable))));
3294 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared))));
3295 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const))));
3296 static assert(!hasUnsharedAliasing!(void function()));
3297
3298 interface I {}
3299 static assert(hasUnsharedAliasing!I);
3300
3301 static assert( hasUnsharedAliasing!(Rebindable!(const Object)));
3302 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object)));
3303 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object)));
3304 static assert( hasUnsharedAliasing!(Rebindable!Object));
3305
3306 /* Issue 6979 */
3307 static assert(!hasUnsharedAliasing!(int, shared(int)*));
3308 static assert( hasUnsharedAliasing!(int, int*));
3309 static assert( hasUnsharedAliasing!(int, const(int)[]));
3310 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object));
3311 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object)));
3312 static assert(!hasUnsharedAliasing!());
3313
3314 struct S9
3315 {
3316 void delegate() shared a;
3317 void delegate() immutable b;
3318 void delegate() shared const c;
3319 shared(void delegate()) d;
3320 shared(void delegate() shared) e;
3321 shared(void delegate() immutable) f;
3322 shared(void delegate() shared const) g;
3323 immutable(void delegate()) h;
3324 immutable(void delegate() shared) i;
3325 immutable(void delegate() immutable) j;
3326 immutable(void delegate() shared const) k;
3327 shared(const(void delegate())) l;
3328 shared(const(void delegate() shared)) m;
3329 shared(const(void delegate() immutable)) n;
3330 shared(const(void delegate() shared const)) o;
3331 }
3332 struct S10 { typeof(S9.tupleof) a; void delegate() p; }
3333 struct S11 { typeof(S9.tupleof) a; Object p; }
3334 struct S12 { typeof(S9.tupleof) a; int* p; }
3335 class S13 { typeof(S9.tupleof) a; }
3336 class S14 { typeof(S9.tupleof) a; void delegate() p; }
3337 class S15 { typeof(S9.tupleof) a; Object p; }
3338 class S16 { typeof(S9.tupleof) a; int* p; }
3339 static assert(!hasUnsharedAliasing!S9);
3340 static assert(!hasUnsharedAliasing!(immutable(S9)));
3341 static assert(!hasUnsharedAliasing!(shared(S9)));
3342 static assert( hasUnsharedAliasing!S10);
3343 static assert(!hasUnsharedAliasing!(immutable(S10)));
3344 static assert(!hasUnsharedAliasing!(shared(S10)));
3345 static assert( hasUnsharedAliasing!S11);
3346 static assert(!hasUnsharedAliasing!(immutable(S11)));
3347 static assert(!hasUnsharedAliasing!(shared(S11)));
3348 static assert( hasUnsharedAliasing!S12);
3349 static assert(!hasUnsharedAliasing!(immutable(S12)));
3350 static assert(!hasUnsharedAliasing!(shared(S12)));
3351 static assert( hasUnsharedAliasing!S13);
3352 static assert(!hasUnsharedAliasing!(immutable(S13)));
3353 static assert(!hasUnsharedAliasing!(shared(S13)));
3354 static assert( hasUnsharedAliasing!S14);
3355 static assert(!hasUnsharedAliasing!(immutable(S14)));
3356 static assert(!hasUnsharedAliasing!(shared(S14)));
3357 static assert( hasUnsharedAliasing!S15);
3358 static assert(!hasUnsharedAliasing!(immutable(S15)));
3359 static assert(!hasUnsharedAliasing!(shared(S15)));
3360 static assert( hasUnsharedAliasing!S16);
3361 static assert(!hasUnsharedAliasing!(immutable(S16)));
3362 static assert(!hasUnsharedAliasing!(shared(S16)));
3363 struct S17 {}
3364 class S18 {}
3365 interface S19 {}
3366 union S20 {}
3367 static assert(!hasUnsharedAliasing!S17);
3368 static assert( hasUnsharedAliasing!S18);
3369 static assert( hasUnsharedAliasing!S19);
3370 static assert(!hasUnsharedAliasing!S20);
3371 }
3372
3373 /**
3374 True if $(D S) or any type embedded directly in the representation of $(D S)
3375 defines an elaborate copy constructor. Elaborate copy constructors are
3376 introduced by defining $(D this(this)) for a $(D struct).
3377
3378 Classes and unions never have elaborate copy constructors.
3379 */
3380 template hasElaborateCopyConstructor(S)
3381 {
3382 import std.meta : anySatisfy;
3383 static if (isStaticArray!S && S.length)
3384 {
3385 enum bool hasElaborateCopyConstructor = hasElaborateCopyConstructor!(typeof(S.init[0]));
3386 }
3387 else static if (is(S == struct))
3388 {
3389 enum hasElaborateCopyConstructor = hasMember!(S, "__postblit")
3390 || anySatisfy!(.hasElaborateCopyConstructor, FieldTypeTuple!S);
3391 }
3392 else
3393 {
3394 enum bool hasElaborateCopyConstructor = false;
3395 }
3396 }
3397
3398 ///
3399 @safe unittest
3400 {
3401 static assert(!hasElaborateCopyConstructor!int);
3402
3403 static struct S1 { }
3404 static struct S2 { this(this) {} }
3405 static struct S3 { S2 field; }
3406 static struct S4 { S3[1] field; }
3407 static struct S5 { S3[] field; }
3408 static struct S6 { S3[0] field; }
3409 static struct S7 { @disable this(); S3 field; }
3410 static assert(!hasElaborateCopyConstructor!S1);
3411 static assert( hasElaborateCopyConstructor!S2);
3412 static assert( hasElaborateCopyConstructor!(immutable S2));
3413 static assert( hasElaborateCopyConstructor!S3);
3414 static assert( hasElaborateCopyConstructor!(S3[1]));
3415 static assert(!hasElaborateCopyConstructor!(S3[0]));
3416 static assert( hasElaborateCopyConstructor!S4);
3417 static assert(!hasElaborateCopyConstructor!S5);
3418 static assert(!hasElaborateCopyConstructor!S6);
3419 static assert( hasElaborateCopyConstructor!S7);
3420 }
3421
3422 /**
3423 True if $(D S) or any type directly embedded in the representation of $(D S)
3424 defines an elaborate assignment. Elaborate assignments are introduced by
3425 defining $(D opAssign(typeof(this))) or $(D opAssign(ref typeof(this)))
3426 for a $(D struct) or when there is a compiler-generated $(D opAssign).
3427
3428 A type $(D S) gets compiler-generated $(D opAssign) in case it has
3429 an elaborate copy constructor or elaborate destructor.
3430
3431 Classes and unions never have elaborate assignments.
3432
3433 Note: Structs with (possibly nested) postblit operator(s) will have a
3434 hidden yet elaborate compiler generated assignment operator (unless
3435 explicitly disabled).
3436 */
3437 template hasElaborateAssign(S)
3438 {
3439 import std.meta : anySatisfy;
3440 static if (isStaticArray!S && S.length)
3441 {
3442 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0]));
3443 }
3444 else static if (is(S == struct))
3445 {
3446 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
3447 is(typeof(S.init.opAssign(lvalueOf!S))) ||
3448 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S);
3449 }
3450 else
3451 {
3452 enum bool hasElaborateAssign = false;
3453 }
3454 }
3455
3456 ///
3457 @safe unittest
3458 {
3459 static assert(!hasElaborateAssign!int);
3460
3461 static struct S { void opAssign(S) {} }
3462 static assert( hasElaborateAssign!S);
3463 static assert(!hasElaborateAssign!(const(S)));
3464
3465 static struct S1 { void opAssign(ref S1) {} }
3466 static struct S2 { void opAssign(int) {} }
3467 static struct S3 { S s; }
3468 static assert( hasElaborateAssign!S1);
3469 static assert(!hasElaborateAssign!S2);
3470 static assert( hasElaborateAssign!S3);
3471 static assert( hasElaborateAssign!(S3[1]));
3472 static assert(!hasElaborateAssign!(S3[0]));
3473 }
3474
3475 @safe unittest
3476 {
3477 static struct S { void opAssign(S) {} }
3478 static struct S4
3479 {
3480 void opAssign(U)(U u) {}
3481 @disable void opAssign(U)(ref U u);
3482 }
3483 static assert( hasElaborateAssign!S4);
3484
3485 static struct S41
3486 {
3487 void opAssign(U)(ref U u) {}
3488 @disable void opAssign(U)(U u);
3489 }
3490 static assert( hasElaborateAssign!S41);
3491
3492 static struct S5 { @disable this(); this(int n){ s = S(); } S s; }
3493 static assert( hasElaborateAssign!S5);
3494
3495 static struct S6 { this(this) {} }
3496 static struct S7 { this(this) {} @disable void opAssign(S7); }
3497 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} }
3498 static struct S9 { this(this) {} void opAssign(int) {} }
3499 static struct S10 { ~this() { } }
3500 static assert( hasElaborateAssign!S6);
3501 static assert(!hasElaborateAssign!S7);
3502 static assert(!hasElaborateAssign!S8);
3503 static assert( hasElaborateAssign!S9);
3504 static assert( hasElaborateAssign!S10);
3505 static struct SS6 { S6 s; }
3506 static struct SS7 { S7 s; }
3507 static struct SS8 { S8 s; }
3508 static struct SS9 { S9 s; }
3509 static assert( hasElaborateAssign!SS6);
3510 static assert(!hasElaborateAssign!SS7);
3511 static assert(!hasElaborateAssign!SS8);
3512 static assert( hasElaborateAssign!SS9);
3513 }
3514
3515 /**
3516 True if $(D S) or any type directly embedded in the representation
3517 of $(D S) defines an elaborate destructor. Elaborate destructors
3518 are introduced by defining $(D ~this()) for a $(D
3519 struct).
3520
3521 Classes and unions never have elaborate destructors, even
3522 though classes may define $(D ~this()).
3523 */
3524 template hasElaborateDestructor(S)
3525 {
3526 import std.meta : anySatisfy;
3527 static if (isStaticArray!S && S.length)
3528 {
3529 enum bool hasElaborateDestructor = hasElaborateDestructor!(typeof(S.init[0]));
3530 }
3531 else static if (is(S == struct))
3532 {
3533 enum hasElaborateDestructor = hasMember!(S, "__dtor")
3534 || anySatisfy!(.hasElaborateDestructor, FieldTypeTuple!S);
3535 }
3536 else
3537 {
3538 enum bool hasElaborateDestructor = false;
3539 }
3540 }
3541
3542 ///
3543 @safe unittest
3544 {
3545 static assert(!hasElaborateDestructor!int);
3546
3547 static struct S1 { }
3548 static struct S2 { ~this() {} }
3549 static struct S3 { S2 field; }
3550 static struct S4 { S3[1] field; }
3551 static struct S5 { S3[] field; }
3552 static struct S6 { S3[0] field; }
3553 static struct S7 { @disable this(); S3 field; }
3554 static assert(!hasElaborateDestructor!S1);
3555 static assert( hasElaborateDestructor!S2);
3556 static assert( hasElaborateDestructor!(immutable S2));
3557 static assert( hasElaborateDestructor!S3);
3558 static assert( hasElaborateDestructor!(S3[1]));
3559 static assert(!hasElaborateDestructor!(S3[0]));
3560 static assert( hasElaborateDestructor!S4);
3561 static assert(!hasElaborateDestructor!S5);
3562 static assert(!hasElaborateDestructor!S6);
3563 static assert( hasElaborateDestructor!S7);
3564 }
3565
3566 package alias Identity(alias A) = A;
3567
3568 /**
3569 Yields $(D true) if and only if $(D T) is an aggregate that defines
3570 a symbol called $(D name).
3571 */
3572 enum hasMember(T, string name) = __traits(hasMember, T, name);
3573
3574 ///
3575 @safe unittest
3576 {
3577 static assert(!hasMember!(int, "blah"));
3578 struct S1 { int blah; }
3579 struct S2 { int blah(){ return 0; } }
3580 class C1 { int blah; }
3581 class C2 { int blah(){ return 0; } }
3582 static assert(hasMember!(S1, "blah"));
3583 static assert(hasMember!(S2, "blah"));
3584 static assert(hasMember!(C1, "blah"));
3585 static assert(hasMember!(C2, "blah"));
3586 }
3587
3588 @safe unittest
3589 {
3590 // 8321
3591 struct S {
3592 int x;
3593 void f(){}
3594 void t()(){}
3595 template T(){}
3596 }
3597 struct R1(T) {
3598 T t;
3599 alias t this;
3600 }
3601 struct R2(T) {
3602 T t;
3603 @property ref inout(T) payload() inout { return t; }
3604 alias t this;
3605 }
3606 static assert(hasMember!(S, "x"));
3607 static assert(hasMember!(S, "f"));
3608 static assert(hasMember!(S, "t"));
3609 static assert(hasMember!(S, "T"));
3610 static assert(hasMember!(R1!S, "x"));
3611 static assert(hasMember!(R1!S, "f"));
3612 static assert(hasMember!(R1!S, "t"));
3613 static assert(hasMember!(R1!S, "T"));
3614 static assert(hasMember!(R2!S, "x"));
3615 static assert(hasMember!(R2!S, "f"));
3616 static assert(hasMember!(R2!S, "t"));
3617 static assert(hasMember!(R2!S, "T"));
3618 }
3619
3620 @safe unittest
3621 {
3622 static struct S
3623 {
3624 void opDispatch(string n, A)(A dummy) {}
3625 }
3626 static assert(hasMember!(S, "foo"));
3627 }
3628
3629 /**
3630 * Whether the symbol represented by the string, member, exists and is a static member of T.
3631 *
3632 * Params:
3633 * T = Type containing symbol $(D member).
3634 * member = Name of symbol to test that resides in $(D T).
3635 *
3636 * Returns:
3637 * $(D true) iff $(D member) exists and is static.
3638 */
3639 template hasStaticMember(T, string member)
3640 {
3641 static if (__traits(hasMember, T, member))
3642 {
3643 import std.meta : Alias;
3644 alias sym = Alias!(__traits(getMember, T, member));
3645
3646 static if (__traits(getOverloads, T, member).length == 0)
3647 enum bool hasStaticMember = __traits(compiles, &sym);
3648 else
3649 enum bool hasStaticMember = __traits(isStaticFunction, sym);
3650 }
3651 else
3652 {
3653 enum bool hasStaticMember = false;
3654 }
3655 }
3656
3657 ///
3658 @safe unittest
3659 {
3660 static struct S
3661 {
3662 static void sf() {}
3663 void f() {}
3664
3665 static int si;
3666 int i;
3667 }
3668
3669 static assert( hasStaticMember!(S, "sf"));
3670 static assert(!hasStaticMember!(S, "f"));
3671
3672 static assert( hasStaticMember!(S, "si"));
3673 static assert(!hasStaticMember!(S, "i"));
3674
3675 static assert(!hasStaticMember!(S, "hello"));
3676 }
3677
3678 @safe unittest
3679 {
3680 static struct S
3681 {
3682 enum X = 10;
3683 enum Y
3684 {
3685 i = 10
3686 }
3687 struct S {}
3688 class C {}
3689
3690 static int sx = 0;
3691 __gshared int gx = 0;
3692
3693 Y y;
3694 static Y sy;
3695
3696 static void f();
3697 static void f2() pure nothrow @nogc @safe;
3698
3699 shared void g();
3700
3701 static void function() fp;
3702 __gshared void function() gfp;
3703 void function() fpm;
3704
3705 void delegate() dm;
3706 static void delegate() sd;
3707
3708 void m();
3709 void m2() const pure nothrow @nogc @safe;
3710
3711 inout(int) iom() inout;
3712 static inout(int) iosf(inout int x);
3713
3714 @property int p();
3715 static @property int sp();
3716 }
3717
3718 static class C
3719 {
3720 enum X = 10;
3721 enum Y
3722 {
3723 i = 10
3724 }
3725 struct S {}
3726 class C {}
3727
3728 static int sx = 0;
3729 __gshared int gx = 0;
3730
3731 Y y;
3732 static Y sy;
3733
3734 static void f();
3735 static void f2() pure nothrow @nogc @safe;
3736
3737 shared void g() { }
3738
3739 static void function() fp;
3740 __gshared void function() gfp;
3741 void function() fpm;
3742
3743 void delegate() dm;
3744 static void delegate() sd;
3745
3746 void m() {}
3747 final void m2() const pure nothrow @nogc @safe;
3748
3749 inout(int) iom() inout { return 10; }
3750 static inout(int) iosf(inout int x);
3751
3752 @property int p() { return 10; }
3753 static @property int sp();
3754 }
3755
3756 static assert(!hasStaticMember!(S, "X"));
3757 static assert(!hasStaticMember!(S, "Y"));
3758 static assert(!hasStaticMember!(S, "Y.i"));
3759 static assert(!hasStaticMember!(S, "S"));
3760 static assert(!hasStaticMember!(S, "C"));
3761 static assert( hasStaticMember!(S, "sx"));
3762 static assert( hasStaticMember!(S, "gx"));
3763 static assert(!hasStaticMember!(S, "y"));
3764 static assert( hasStaticMember!(S, "sy"));
3765 static assert( hasStaticMember!(S, "f"));
3766 static assert( hasStaticMember!(S, "f2"));
3767 static assert(!hasStaticMember!(S, "dm"));
3768 static assert( hasStaticMember!(S, "sd"));
3769 static assert(!hasStaticMember!(S, "g"));
3770 static assert( hasStaticMember!(S, "fp"));
3771 static assert( hasStaticMember!(S, "gfp"));
3772 static assert(!hasStaticMember!(S, "fpm"));
3773 static assert(!hasStaticMember!(S, "m"));
3774 static assert(!hasStaticMember!(S, "m2"));
3775 static assert(!hasStaticMember!(S, "iom"));
3776 static assert( hasStaticMember!(S, "iosf"));
3777 static assert(!hasStaticMember!(S, "p"));
3778 static assert( hasStaticMember!(S, "sp"));
3779
3780 static assert(!hasStaticMember!(C, "X"));
3781 static assert(!hasStaticMember!(C, "Y"));
3782 static assert(!hasStaticMember!(C, "Y.i"));
3783 static assert(!hasStaticMember!(C, "S"));
3784 static assert(!hasStaticMember!(C, "C"));
3785 static assert( hasStaticMember!(C, "sx"));
3786 static assert( hasStaticMember!(C, "gx"));
3787 static assert(!hasStaticMember!(C, "y"));
3788 static assert( hasStaticMember!(C, "sy"));
3789 static assert( hasStaticMember!(C, "f"));
3790 static assert( hasStaticMember!(C, "f2"));
3791 static assert(!hasStaticMember!(S, "dm"));
3792 static assert( hasStaticMember!(S, "sd"));
3793 static assert(!hasStaticMember!(C, "g"));
3794 static assert( hasStaticMember!(C, "fp"));
3795 static assert( hasStaticMember!(C, "gfp"));
3796 static assert(!hasStaticMember!(C, "fpm"));
3797 static assert(!hasStaticMember!(C, "m"));
3798 static assert(!hasStaticMember!(C, "m2"));
3799 static assert(!hasStaticMember!(C, "iom"));
3800 static assert( hasStaticMember!(C, "iosf"));
3801 static assert(!hasStaticMember!(C, "p"));
3802 static assert( hasStaticMember!(C, "sp"));
3803 }
3804
3805 /**
3806 Retrieves the members of an enumerated type $(D enum E).
3807
3808 Params:
3809 E = An enumerated type. $(D E) may have duplicated values.
3810
3811 Returns:
3812 Static tuple composed of the members of the enumerated type $(D E).
3813 The members are arranged in the same order as declared in $(D E).
3814
3815 Note:
3816 An enum can have multiple members which have the same value. If you want
3817 to use EnumMembers to e.g. generate switch cases at compile-time,
3818 you should use the $(REF NoDuplicates, std,meta) template to avoid
3819 generating duplicate switch cases.
3820
3821 Note:
3822 Returned values are strictly typed with $(D E). Thus, the following code
3823 does not work without the explicit cast:
3824 --------------------
3825 enum E : int { a, b, c }
3826 int[] abc = cast(int[]) [ EnumMembers!E ];
3827 --------------------
3828 Cast is not necessary if the type of the variable is inferred. See the
3829 example below.
3830
3831 Example:
3832 Creating an array of enumerated values:
3833 --------------------
3834 enum Sqrts : real
3835 {
3836 one = 1,
3837 two = 1.41421,
3838 three = 1.73205,
3839 }
3840 auto sqrts = [ EnumMembers!Sqrts ];
3841 assert(sqrts == [ Sqrts.one, Sqrts.two, Sqrts.three ]);
3842 --------------------
3843
3844 A generic function $(D rank(v)) in the following example uses this
3845 template for finding a member $(D e) in an enumerated type $(D E).
3846 --------------------
3847 // Returns i if e is the i-th enumerator of E.
3848 size_t rank(E)(E e)
3849 if (is(E == enum))
3850 {
3851 foreach (i, member; EnumMembers!E)
3852 {
3853 if (e == member)
3854 return i;
3855 }
3856 assert(0, "Not an enum member");
3857 }
3858
3859 enum Mode
3860 {
3861 read = 1,
3862 write = 2,
3863 map = 4,
3864 }
3865 assert(rank(Mode.read ) == 0);
3866 assert(rank(Mode.write) == 1);
3867 assert(rank(Mode.map ) == 2);
3868 --------------------
3869 */
3870 template EnumMembers(E)
3871 if (is(E == enum))
3872 {
3873 import std.meta : AliasSeq;
3874 // Supply the specified identifier to an constant value.
3875 template WithIdentifier(string ident)
3876 {
3877 static if (ident == "Symbolize")
3878 {
3879 template Symbolize(alias value)
3880 {
3881 enum Symbolize = value;
3882 }
3883 }
3884 else
3885 {
3886 mixin("template Symbolize(alias "~ ident ~")"
3887 ~"{"
3888 ~"alias Symbolize = "~ ident ~";"
3889 ~"}");
3890 }
3891 }
3892
3893 template EnumSpecificMembers(names...)
3894 {
3895 static if (names.length == 1)
3896 {
3897 alias EnumSpecificMembers = AliasSeq!(WithIdentifier!(names[0])
3898 .Symbolize!(__traits(getMember, E, names[0])));
3899 }
3900 else static if (names.length > 0)
3901 {
3902 alias EnumSpecificMembers =
3903 AliasSeq!(
3904 WithIdentifier!(names[0])
3905 .Symbolize!(__traits(getMember, E, names[0])),
3906 EnumSpecificMembers!(names[1 .. $/2]),
3907 EnumSpecificMembers!(names[$/2..$])
3908 );
3909 }
3910 else
3911 {
3912 alias EnumSpecificMembers = AliasSeq!();
3913 }
3914 }
3915
3916 alias EnumMembers = EnumSpecificMembers!(__traits(allMembers, E));
3917 }
3918
3919 @safe unittest
3920 {
3921 enum A { a }
3922 static assert([ EnumMembers!A ] == [ A.a ]);
3923 enum B { a, b, c, d, e }
3924 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]);
3925 }
3926
3927 @safe unittest // typed enums
3928 {
3929 enum A : string { a = "alpha", b = "beta" }
3930 static assert([ EnumMembers!A ] == [ A.a, A.b ]);
3931
3932 static struct S
3933 {
3934 int value;
3935 int opCmp(S rhs) const nothrow { return value - rhs.value; }
3936 }
3937 enum B : S { a = S(1), b = S(2), c = S(3) }
3938 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]);
3939 }
3940
3941 @safe unittest // duplicated values
3942 {
3943 enum A
3944 {
3945 a = 0, b = 0,
3946 c = 1, d = 1, e
3947 }
3948 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]);
3949 }
3950
3951 @safe unittest // Bugzilla 14561: huge enums
3952 {
3953 string genEnum()
3954 {
3955 string result = "enum TLAs {";
3956 foreach (c0; '0'..'2'+1)
3957 foreach (c1; '0'..'9'+1)
3958 foreach (c2; '0'..'9'+1)
3959 foreach (c3; '0'..'9'+1)
3960 {
3961 result ~= '_';
3962 result ~= c0;
3963 result ~= c1;
3964 result ~= c2;
3965 result ~= c3;
3966 result ~= ',';
3967 }
3968 result ~= '}';
3969 return result;
3970 }
3971 mixin(genEnum);
3972 static assert(EnumMembers!TLAs[0] == TLAs._0000);
3973 static assert(EnumMembers!TLAs[$-1] == TLAs._2999);
3974 }
3975
3976 @safe unittest
3977 {
3978 enum E { member, a = 0, b = 0 }
3979 static assert(__traits(identifier, EnumMembers!E[0]) == "member");
3980 static assert(__traits(identifier, EnumMembers!E[1]) == "a");
3981 static assert(__traits(identifier, EnumMembers!E[2]) == "b");
3982 }
3983
3984
3985 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3986 // Classes and Interfaces
3987 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3988
3989 /***
3990 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
3991 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
3992 * the empty type tuple.
3993 */
3994 template BaseTypeTuple(A)
3995 {
3996 static if (is(A P == super))
3997 alias BaseTypeTuple = P;
3998 else
3999 static assert(0, "argument is not a class or interface");
4000 }
4001
4002 ///
4003 @safe unittest
4004 {
4005 interface I1 { }
4006 interface I2 { }
4007 interface I12 : I1, I2 { }
4008 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));
4009
4010 interface I3 : I1 { }
4011 interface I123 : I1, I2, I3 { }
4012 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));
4013 }
4014
4015 @safe unittest
4016 {
4017 interface I1 { }
4018 interface I2 { }
4019 class A { }
4020 class C : A, I1, I2 { }
4021
4022 alias TL = BaseTypeTuple!C;
4023 assert(TL.length == 3);
4024 assert(is (TL[0] == A));
4025 assert(is (TL[1] == I1));
4026 assert(is (TL[2] == I2));
4027
4028 assert(BaseTypeTuple!Object.length == 0);
4029 }
4030
4031 /**
4032 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4033 * in decreasing order. Interfaces are not included. $(D_PARAM
4034 * BaseClassesTuple!Object) yields the empty type tuple.
4035 */
4036 template BaseClassesTuple(T)
4037 if (is(T == class))
4038 {
4039 static if (is(T == Object))
4040 {
4041 alias BaseClassesTuple = AliasSeq!();
4042 }
4043 else static if (is(BaseTypeTuple!T[0] == Object))
4044 {
4045 alias BaseClassesTuple = AliasSeq!Object;
4046 }
4047 else
4048 {
4049 alias BaseClassesTuple =
4050 AliasSeq!(BaseTypeTuple!T[0],
4051 BaseClassesTuple!(BaseTypeTuple!T[0]));
4052 }
4053 }
4054
4055 ///
4056 @safe unittest
4057 {
4058 class C1 { }
4059 class C2 : C1 { }
4060 class C3 : C2 { }
4061 static assert(!BaseClassesTuple!Object.length);
4062 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
4063 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
4064 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));
4065 }
4066
4067 @safe unittest
4068 {
4069 struct S { }
4070 static assert(!__traits(compiles, BaseClassesTuple!S));
4071 interface I { }
4072 static assert(!__traits(compiles, BaseClassesTuple!I));
4073 class C4 : I { }
4074 class C5 : C4, I { }
4075 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object)));
4076 }
4077
4078 /**
4079 * Get a $(D_PARAM AliasSeq) of $(I all) interfaces directly or
4080 * indirectly inherited by this class or interface. Interfaces do not
4081 * repeat if multiply implemented. $(D_PARAM InterfacesTuple!Object)
4082 * yields the empty type tuple.
4083 */
4084 template InterfacesTuple(T)
4085 {
4086 import std.meta : NoDuplicates;
4087 template Flatten(H, T...)
4088 {
4089 static if (T.length)
4090 {
4091 alias Flatten = AliasSeq!(Flatten!H, Flatten!T);
4092 }
4093 else
4094 {
4095 static if (is(H == interface))
4096 alias Flatten = AliasSeq!(H, InterfacesTuple!H);
4097 else
4098 alias Flatten = InterfacesTuple!H;
4099 }
4100 }
4101
4102 static if (is(T S == super) && S.length)
4103 alias InterfacesTuple = NoDuplicates!(Flatten!S);
4104 else
4105 alias InterfacesTuple = AliasSeq!();
4106 }
4107
4108 @safe unittest
4109 {
4110 // doc example
4111 interface I1 {}
4112 interface I2 {}
4113 class A : I1, I2 { }
4114 class B : A, I1 { }
4115 class C : B { }
4116 alias TL = InterfacesTuple!C;
4117 static assert(is(TL[0] == I1) && is(TL[1] == I2));
4118 }
4119
4120 @safe unittest
4121 {
4122 interface Iaa {}
4123 interface Iab {}
4124 interface Iba {}
4125 interface Ibb {}
4126 interface Ia : Iaa, Iab {}
4127 interface Ib : Iba, Ibb {}
4128 interface I : Ia, Ib {}
4129 interface J {}
4130 class B2 : J {}
4131 class C2 : B2, Ia, Ib {}
4132 static assert(is(InterfacesTuple!I ==
4133 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb)));
4134 static assert(is(InterfacesTuple!C2 ==
4135 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb)));
4136
4137 }
4138
4139 /**
4140 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4141 * T), in decreasing order, followed by $(D_PARAM T)'s
4142 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4143 * empty type tuple.
4144 */
4145 template TransitiveBaseTypeTuple(T)
4146 {
4147 static if (is(T == Object))
4148 alias TransitiveBaseTypeTuple = AliasSeq!();
4149 else
4150 alias TransitiveBaseTypeTuple =
4151 AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
4152 }
4153
4154 ///
4155 @safe unittest
4156 {
4157 interface J1 {}
4158 interface J2 {}
4159 class B1 {}
4160 class B2 : B1, J1, J2 {}
4161 class B3 : B2, J1 {}
4162 alias TL = TransitiveBaseTypeTuple!B3;
4163 assert(TL.length == 5);
4164 assert(is (TL[0] == B2));
4165 assert(is (TL[1] == B1));
4166 assert(is (TL[2] == Object));
4167 assert(is (TL[3] == J1));
4168 assert(is (TL[4] == J2));
4169
4170 assert(TransitiveBaseTypeTuple!Object.length == 0);
4171 }
4172
4173
4174 /**
4175 Returns a tuple of non-static functions with the name $(D name) declared in the
4176 class or interface $(D C). Covariant duplicates are shrunk into the most
4177 derived one.
4178 */
4179 template MemberFunctionsTuple(C, string name)
4180 if (is(C == class) || is(C == interface))
4181 {
4182 static if (__traits(hasMember, C, name))
4183 {
4184 /*
4185 * First, collect all overloads in the class hierarchy.
4186 */
4187 template CollectOverloads(Node)
4188 {
4189 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
4190 {
4191 // Get all overloads in sight (not hidden).
4192 alias inSight = AliasSeq!(__traits(getVirtualFunctions, Node, name));
4193
4194 // And collect all overloads in ancestor classes to reveal hidden
4195 // methods. The result may contain duplicates.
4196 template walkThru(Parents...)
4197 {
4198 static if (Parents.length > 0)
4199 alias walkThru = AliasSeq!(
4200 CollectOverloads!(Parents[0]),
4201 walkThru!(Parents[1 .. $])
4202 );
4203 else
4204 alias walkThru = AliasSeq!();
4205 }
4206
4207 static if (is(Node Parents == super))
4208 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents);
4209 else
4210 alias CollectOverloads = AliasSeq!inSight;
4211 }
4212 else
4213 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy
4214 }
4215
4216 // duplicates in this tuple will be removed by shrink()
4217 alias overloads = CollectOverloads!C;
4218
4219 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4220 // shrinkOne!args[1..$] = non-covariant others
4221 template shrinkOne(/+ alias target, rest... +/ args...)
4222 {
4223 import std.meta : AliasSeq;
4224 alias target = args[0 .. 1]; // prevent property functions from being evaluated
4225 alias rest = args[1 .. $];
4226
4227 static if (rest.length > 0)
4228 {
4229 alias Target = FunctionTypeOf!target;
4230 alias Rest0 = FunctionTypeOf!(rest[0]);
4231
4232 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target))
4233 {
4234 // One of these overrides the other. Choose the one from the most derived parent.
4235 static if (is(AliasSeq!(__traits(parent, target))[0] : AliasSeq!(__traits(parent, rest[0]))[0]))
4236 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4237 else
4238 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4239 }
4240 else static if (isCovariantWith!(Target, Rest0))
4241 // target overrides rest[0] -- erase rest[0].
4242 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4243 else static if (isCovariantWith!(Rest0, Target))
4244 // rest[0] overrides target -- erase target.
4245 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4246 else
4247 // target and rest[0] are distinct.
4248 alias shrinkOne = AliasSeq!(
4249 shrinkOne!(target, rest[1 .. $]),
4250 rest[0] // keep
4251 );
4252 }
4253 else
4254 alias shrinkOne = AliasSeq!target; // done
4255 }
4256
4257 /*
4258 * Now shrink covariant overloads into one.
4259 */
4260 template shrink(overloads...)
4261 {
4262 static if (overloads.length > 0)
4263 {
4264 alias temp = shrinkOne!overloads;
4265 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $]));
4266 }
4267 else
4268 alias shrink = AliasSeq!(); // done
4269 }
4270
4271 // done.
4272 alias MemberFunctionsTuple = shrink!overloads;
4273 }
4274 else
4275 alias MemberFunctionsTuple = AliasSeq!();
4276 }
4277
4278 ///
4279 @safe unittest
4280 {
4281 interface I { I foo(); }
4282 class B
4283 {
4284 real foo(real v) { return v; }
4285 }
4286 class C : B, I
4287 {
4288 override C foo() { return this; } // covariant overriding of I.foo()
4289 }
4290 alias foos = MemberFunctionsTuple!(C, "foo");
4291 static assert(foos.length == 2);
4292 static assert(__traits(isSame, foos[0], C.foo));
4293 static assert(__traits(isSame, foos[1], B.foo));
4294 }
4295
4296 @safe unittest // Issue 15920
4297 {
4298 import std.meta : AliasSeq;
4299 class A
4300 {
4301 void f(){}
4302 void f(int){}
4303 }
4304 class B : A
4305 {
4306 override void f(){}
4307 override void f(int){}
4308 }
4309 alias fs = MemberFunctionsTuple!(B, "f");
4310 alias bfs = AliasSeq!(__traits(getOverloads, B, "f"));
4311 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1]));
4312 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1]));
4313 }
4314
4315 @safe unittest
4316 {
4317 interface I { I test(); }
4318 interface J : I { J test(); }
4319 interface K { K test(int); }
4320 class B : I, K
4321 {
4322 K test(int) { return this; }
4323 B test() { return this; }
4324 static void test(string) { }
4325 }
4326 class C : B, J
4327 {
4328 override C test() { return this; }
4329 }
4330 alias test =MemberFunctionsTuple!(C, "test");
4331 static assert(test.length == 2);
4332 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test)));
4333 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test)));
4334 alias noexist = MemberFunctionsTuple!(C, "noexist");
4335 static assert(noexist.length == 0);
4336
4337 interface L { int prop() @property; }
4338 alias prop = MemberFunctionsTuple!(L, "prop");
4339 static assert(prop.length == 1);
4340
4341 interface Test_I
4342 {
4343 void foo();
4344 void foo(int);
4345 void foo(int, int);
4346 }
4347 interface Test : Test_I {}
4348 alias Test_foo = MemberFunctionsTuple!(Test, "foo");
4349 static assert(Test_foo.length == 3);
4350 static assert(is(typeof(&Test_foo[0]) == void function()));
4351 static assert(is(typeof(&Test_foo[2]) == void function(int)));
4352 static assert(is(typeof(&Test_foo[1]) == void function(int, int)));
4353 }
4354
4355
4356 /**
4357 Returns an alias to the template that $(D T) is an instance of.
4358 */
4359 template TemplateOf(alias T : Base!Args, alias Base, Args...)
4360 {
4361 alias TemplateOf = Base;
4362 }
4363
4364 /// ditto
4365 template TemplateOf(T : Base!Args, alias Base, Args...)
4366 {
4367 alias TemplateOf = Base;
4368 }
4369
4370 ///
4371 @safe unittest
4372 {
4373 struct Foo(T, U) {}
4374 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4375 }
4376
4377 @safe unittest
4378 {
4379 template Foo1(A) {}
4380 template Foo2(A, B) {}
4381 template Foo3(alias A) {}
4382 template Foo4(string A) {}
4383 struct Foo5(A) {}
4384 struct Foo6(A, B) {}
4385 struct Foo7(alias A) {}
4386 template Foo8(A) { template Foo9(B) {} }
4387 template Foo10() {}
4388
4389 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4390 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4391 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4392 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4393 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4394 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4395 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4396 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4397 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4398 }
4399
4400
4401 /**
4402 Returns a $(D AliasSeq) of the template arguments used to instantiate $(D T).
4403 */
4404 template TemplateArgsOf(alias T : Base!Args, alias Base, Args...)
4405 {
4406 alias TemplateArgsOf = Args;
4407 }
4408
4409 /// ditto
4410 template TemplateArgsOf(T : Base!Args, alias Base, Args...)
4411 {
4412 alias TemplateArgsOf = Args;
4413 }
4414
4415 ///
4416 @safe unittest
4417 {
4418 struct Foo(T, U) {}
4419 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4420 }
4421
4422 @safe unittest
4423 {
4424 template Foo1(A) {}
4425 template Foo2(A, B) {}
4426 template Foo3(alias A) {}
4427 template Foo4(string A) {}
4428 struct Foo5(A) {}
4429 struct Foo6(A, B) {}
4430 struct Foo7(alias A) {}
4431 template Foo8(A) { template Foo9(B) {} }
4432 template Foo10() {}
4433
4434 enum x = 123;
4435 enum y = "123";
4436 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4437 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4438 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4439 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4440 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4441 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4442 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4443 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4444 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4445 }
4446
4447
4448 private template maxAlignment(U...) if (isTypeTuple!U)
4449 {
4450 import std.meta : staticMap;
4451 static if (U.length == 0)
4452 static assert(0);
4453 else static if (U.length == 1)
4454 enum maxAlignment = U[0].alignof;
4455 else
4456 {
4457 import std.algorithm.comparison : max;
4458 enum maxAlignment = max(staticMap!(.maxAlignment, U));
4459 }
4460 }
4461
4462
4463 /**
4464 Returns class instance alignment.
4465 */
4466 template classInstanceAlignment(T) if (is(T == class))
4467 {
4468 alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof));
4469 }
4470
4471 ///
4472 @safe unittest
4473 {
4474 class A { byte b; }
4475 class B { long l; }
4476
4477 // As class instance always has a hidden pointer
4478 static assert(classInstanceAlignment!A == (void*).alignof);
4479 static assert(classInstanceAlignment!B == long.alignof);
4480 }
4481
4482
4483 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4484 // Type Conversion
4485 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4486
4487 /**
4488 Get the type that all types can be implicitly converted to. Useful
4489 e.g. in figuring out an array type from a bunch of initializing
4490 values. Returns $(D_PARAM void) if passed an empty list, or if the
4491 types have no common type.
4492 */
4493 template CommonType(T...)
4494 {
4495 static if (!T.length)
4496 {
4497 alias CommonType = void;
4498 }
4499 else static if (T.length == 1)
4500 {
4501 static if (is(typeof(T[0])))
4502 {
4503 alias CommonType = typeof(T[0]);
4504 }
4505 else
4506 {
4507 alias CommonType = T[0];
4508 }
4509 }
4510 else static if (is(typeof(true ? T[0].init : T[1].init) U))
4511 {
4512 alias CommonType = CommonType!(U, T[2 .. $]);
4513 }
4514 else
4515 alias CommonType = void;
4516 }
4517
4518 ///
4519 @safe unittest
4520 {
4521 alias X = CommonType!(int, long, short);
4522 assert(is(X == long));
4523 alias Y = CommonType!(int, char[], short);
4524 assert(is(Y == void));
4525 }
4526 @safe unittest
4527 {
4528 static assert(is(CommonType!(3) == int));
4529 static assert(is(CommonType!(double, 4, float) == double));
4530 static assert(is(CommonType!(string, char[]) == const(char)[]));
4531 static assert(is(CommonType!(3, 3U) == uint));
4532 }
4533
4534
4535 /**
4536 * Returns a tuple with all possible target types of an implicit
4537 * conversion of a value of type $(D_PARAM T).
4538 *
4539 * Important note:
4540 *
4541 * The possible targets are computed more conservatively than the D
4542 * 2.005 compiler does, eliminating all dangerous conversions. For
4543 * example, $(D_PARAM ImplicitConversionTargets!double) does not
4544 * include $(D_PARAM float).
4545 */
4546 template ImplicitConversionTargets(T)
4547 {
4548 static if (is(T == bool))
4549 alias ImplicitConversionTargets =
4550 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
4551 float, double, real, char, wchar, dchar);
4552 else static if (is(T == byte))
4553 alias ImplicitConversionTargets =
4554 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
4555 float, double, real, char, wchar, dchar);
4556 else static if (is(T == ubyte))
4557 alias ImplicitConversionTargets =
4558 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
4559 float, double, real, char, wchar, dchar);
4560 else static if (is(T == short))
4561 alias ImplicitConversionTargets =
4562 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
4563 else static if (is(T == ushort))
4564 alias ImplicitConversionTargets =
4565 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
4566 else static if (is(T == int))
4567 alias ImplicitConversionTargets =
4568 AliasSeq!(long, ulong, CentTypeList, float, double, real);
4569 else static if (is(T == uint))
4570 alias ImplicitConversionTargets =
4571 AliasSeq!(long, ulong, CentTypeList, float, double, real);
4572 else static if (is(T == long))
4573 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
4574 else static if (is(T == ulong))
4575 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
4576 else static if (is(cent) && is(T == cent))
4577 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
4578 else static if (is(ucent) && is(T == ucent))
4579 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
4580 else static if (is(T == float))
4581 alias ImplicitConversionTargets = AliasSeq!(double, real);
4582 else static if (is(T == double))
4583 alias ImplicitConversionTargets = AliasSeq!real;
4584 else static if (is(T == char))
4585 alias ImplicitConversionTargets =
4586 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
4587 int, uint, long, ulong, CentTypeList, float, double, real);
4588 else static if (is(T == wchar))
4589 alias ImplicitConversionTargets =
4590 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
4591 float, double, real);
4592 else static if (is(T == dchar))
4593 alias ImplicitConversionTargets =
4594 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
4595 else static if (is(T : typeof(null)))
4596 alias ImplicitConversionTargets = AliasSeq!(typeof(null));
4597 else static if (is(T : Object))
4598 alias ImplicitConversionTargets = TransitiveBaseTypeTuple!(T);
4599 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4600 alias ImplicitConversionTargets =
4601 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4602 else static if (is(T : void*))
4603 alias ImplicitConversionTargets = AliasSeq!(void*);
4604 else
4605 alias ImplicitConversionTargets = AliasSeq!();
4606 }
4607
4608 @safe unittest
4609 {
4610 static assert(is(ImplicitConversionTargets!(double)[0] == real));
4611 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
4612 }
4613
4614 /**
4615 Is $(D From) implicitly convertible to $(D To)?
4616 */
4617 template isImplicitlyConvertible(From, To)
4618 {
4619 enum bool isImplicitlyConvertible = is(typeof({
4620 void fun(ref From v)
4621 {
4622 void gun(To) {}
4623 gun(v);
4624 }
4625 }));
4626 }
4627
4628 ///
4629 @safe unittest
4630 {
4631 static assert( isImplicitlyConvertible!(immutable(char), char));
4632 static assert( isImplicitlyConvertible!(const(char), char));
4633 static assert( isImplicitlyConvertible!(char, wchar));
4634 static assert(!isImplicitlyConvertible!(wchar, char));
4635
4636 static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
4637 static assert(!isImplicitlyConvertible!(const(uint), ubyte));
4638 static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
4639
4640 static assert(!isImplicitlyConvertible!(const(char)[], string));
4641 static assert( isImplicitlyConvertible!(string, const(char)[]));
4642 }
4643
4644 /**
4645 Returns $(D true) iff a value of type $(D Rhs) can be assigned to a variable of
4646 type $(D Lhs).
4647
4648 $(D isAssignable) returns whether both an lvalue and rvalue can be assigned.
4649
4650 If you omit $(D Rhs), $(D isAssignable) will check identity assignable of $(D Lhs).
4651 */
4652 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
4653
4654 ///
4655 @safe unittest
4656 {
4657 static assert( isAssignable!(long, int));
4658 static assert(!isAssignable!(int, long));
4659 static assert( isAssignable!(const(char)[], string));
4660 static assert(!isAssignable!(string, char[]));
4661
4662 // int is assignable to int
4663 static assert( isAssignable!int);
4664
4665 // immutable int is not assignable to immutable int
4666 static assert(!isAssignable!(immutable int));
4667 }
4668
4669 // ditto
4670 private enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, lvalueOf!Lhs = rvalueOf!Rhs);
4671
4672 // ditto
4673 private enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, lvalueOf!Lhs = lvalueOf!Rhs);
4674
4675 @safe unittest
4676 {
4677 static assert(!isAssignable!(immutable int, int));
4678 static assert( isAssignable!(int, immutable int));
4679
4680 static assert(!isAssignable!(inout int, int));
4681 static assert( isAssignable!(int, inout int));
4682 static assert(!isAssignable!(inout int));
4683
4684 static assert( isAssignable!(shared int, int));
4685 static assert( isAssignable!(int, shared int));
4686 static assert( isAssignable!(shared int));
4687
4688 static assert( isAssignable!(void[1], void[1]));
4689
4690 struct S { @disable this(); this(int n){} }
4691 static assert( isAssignable!(S, S));
4692
4693 struct S2 { this(int n){} }
4694 static assert( isAssignable!(S2, S2));
4695 static assert(!isAssignable!(S2, int));
4696
4697 struct S3 { @disable void opAssign(); }
4698 static assert( isAssignable!(S3, S3));
4699
4700 struct S3X { @disable void opAssign(S3X); }
4701 static assert(!isAssignable!(S3X, S3X));
4702
4703 struct S4 { void opAssign(int); }
4704 static assert( isAssignable!(S4, S4));
4705 static assert( isAssignable!(S4, int));
4706 static assert( isAssignable!(S4, immutable int));
4707
4708 struct S5 { @disable this(); @disable this(this); }
4709 struct S6 { void opAssign(in ref S5); }
4710 static assert(!isAssignable!(S6, S5));
4711 static assert(!isRvalueAssignable!(S6, S5));
4712 static assert( isLvalueAssignable!(S6, S5));
4713 static assert( isLvalueAssignable!(S6, immutable S5));
4714 }
4715
4716
4717 // Equivalent with TypeStruct::isAssignable in compiler code.
4718 package template isBlitAssignable(T)
4719 {
4720 static if (is(OriginalType!T U) && !is(T == U))
4721 {
4722 enum isBlitAssignable = isBlitAssignable!U;
4723 }
4724 else static if (isStaticArray!T && is(T == E[n], E, size_t n))
4725 // Workaround for issue 11499 : isStaticArray!T should not be necessary.
4726 {
4727 enum isBlitAssignable = isBlitAssignable!E;
4728 }
4729 else static if (is(T == struct) || is(T == union))
4730 {
4731 enum isBlitAssignable = isMutable!T &&
4732 {
4733 size_t offset = 0;
4734 bool assignable = true;
4735 foreach (i, F; FieldTypeTuple!T)
4736 {
4737 static if (i == 0)
4738 {
4739 }
4740 else
4741 {
4742 if (T.tupleof[i].offsetof == offset)
4743 {
4744 if (assignable)
4745 continue;
4746 }
4747 else
4748 {
4749 if (!assignable)
4750 return false;
4751 }
4752 }
4753 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
4754 offset = T.tupleof[i].offsetof;
4755 }
4756 return assignable;
4757 }();
4758 }
4759 else
4760 enum isBlitAssignable = isMutable!T;
4761 }
4762
4763 @safe unittest
4764 {
4765 static assert( isBlitAssignable!int);
4766 static assert(!isBlitAssignable!(const int));
4767
4768 class C{ const int i; }
4769 static assert( isBlitAssignable!C);
4770
4771 struct S1{ int i; }
4772 struct S2{ const int i; }
4773 static assert( isBlitAssignable!S1);
4774 static assert(!isBlitAssignable!S2);
4775
4776 struct S3X { union { int x; int y; } }
4777 struct S3Y { union { int x; const int y; } }
4778 struct S3Z { union { const int x; const int y; } }
4779 static assert( isBlitAssignable!(S3X));
4780 static assert( isBlitAssignable!(S3Y));
4781 static assert(!isBlitAssignable!(S3Z));
4782 static assert(!isBlitAssignable!(const S3X));
4783 static assert(!isBlitAssignable!(inout S3Y));
4784 static assert(!isBlitAssignable!(immutable S3Z));
4785 static assert( isBlitAssignable!(S3X[3]));
4786 static assert( isBlitAssignable!(S3Y[3]));
4787 static assert(!isBlitAssignable!(S3Z[3]));
4788 enum ES3X : S3X { a = S3X() }
4789 enum ES3Y : S3Y { a = S3Y() }
4790 enum ES3Z : S3Z { a = S3Z() }
4791 static assert( isBlitAssignable!(ES3X));
4792 static assert( isBlitAssignable!(ES3Y));
4793 static assert(!isBlitAssignable!(ES3Z));
4794 static assert(!isBlitAssignable!(const ES3X));
4795 static assert(!isBlitAssignable!(inout ES3Y));
4796 static assert(!isBlitAssignable!(immutable ES3Z));
4797 static assert( isBlitAssignable!(ES3X[3]));
4798 static assert( isBlitAssignable!(ES3Y[3]));
4799 static assert(!isBlitAssignable!(ES3Z[3]));
4800
4801 union U1X { int x; int y; }
4802 union U1Y { int x; const int y; }
4803 union U1Z { const int x; const int y; }
4804 static assert( isBlitAssignable!(U1X));
4805 static assert( isBlitAssignable!(U1Y));
4806 static assert(!isBlitAssignable!(U1Z));
4807 static assert(!isBlitAssignable!(const U1X));
4808 static assert(!isBlitAssignable!(inout U1Y));
4809 static assert(!isBlitAssignable!(immutable U1Z));
4810 static assert( isBlitAssignable!(U1X[3]));
4811 static assert( isBlitAssignable!(U1Y[3]));
4812 static assert(!isBlitAssignable!(U1Z[3]));
4813 enum EU1X : U1X { a = U1X() }
4814 enum EU1Y : U1Y { a = U1Y() }
4815 enum EU1Z : U1Z { a = U1Z() }
4816 static assert( isBlitAssignable!(EU1X));
4817 static assert( isBlitAssignable!(EU1Y));
4818 static assert(!isBlitAssignable!(EU1Z));
4819 static assert(!isBlitAssignable!(const EU1X));
4820 static assert(!isBlitAssignable!(inout EU1Y));
4821 static assert(!isBlitAssignable!(immutable EU1Z));
4822 static assert( isBlitAssignable!(EU1X[3]));
4823 static assert( isBlitAssignable!(EU1Y[3]));
4824 static assert(!isBlitAssignable!(EU1Z[3]));
4825
4826 struct SA
4827 {
4828 @property int[3] foo() { return [1,2,3]; }
4829 alias foo this;
4830 const int x; // SA is not blit assignable
4831 }
4832 static assert(!isStaticArray!SA);
4833 static assert(!isBlitAssignable!(SA[3]));
4834 }
4835
4836
4837 /*
4838 Works like $(D isImplicitlyConvertible), except this cares only about storage
4839 classes of the arguments.
4840 */
4841 private template isStorageClassImplicitlyConvertible(From, To)
4842 {
4843 alias Pointify(T) = void*;
4844
4845 enum isStorageClassImplicitlyConvertible = isImplicitlyConvertible!(
4846 ModifyTypePreservingTQ!(Pointify, From),
4847 ModifyTypePreservingTQ!(Pointify, To) );
4848 }
4849
4850 @safe unittest
4851 {
4852 static assert( isStorageClassImplicitlyConvertible!( int, const int));
4853 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
4854
4855 static assert(!isStorageClassImplicitlyConvertible!(const int, int));
4856 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
4857 static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
4858 static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
4859 }
4860
4861
4862 /**
4863 Determines whether the function type $(D F) is covariant with $(D G), i.e.,
4864 functions of the type $(D F) can override ones of the type $(D G).
4865 */
4866 template isCovariantWith(F, G)
4867 if (is(F == function) && is(G == function))
4868 {
4869 static if (is(F : G))
4870 enum isCovariantWith = true;
4871 else
4872 {
4873 alias Upr = F;
4874 alias Lwr = G;
4875
4876 /*
4877 * Check for calling convention: require exact match.
4878 */
4879 template checkLinkage()
4880 {
4881 enum ok = functionLinkage!Upr == functionLinkage!Lwr;
4882 }
4883 /*
4884 * Check for variadic parameter: require exact match.
4885 */
4886 template checkVariadicity()
4887 {
4888 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
4889 }
4890 /*
4891 * Check for function storage class:
4892 * - overrider can have narrower storage class than base
4893 */
4894 template checkSTC()
4895 {
4896 // Note the order of arguments. The convertion order Lwr -> Upr is
4897 // correct since Upr should be semantically 'narrower' than Lwr.
4898 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
4899 }
4900 /*
4901 * Check for function attributes:
4902 * - require exact match for ref and @property
4903 * - overrider can add pure and nothrow, but can't remove them
4904 * - @safe and @trusted are covariant with each other, unremovable
4905 */
4906 template checkAttributes()
4907 {
4908 alias FA = FunctionAttribute;
4909 enum uprAtts = functionAttributes!Upr;
4910 enum lwrAtts = functionAttributes!Lwr;
4911 //
4912 enum wantExact = FA.ref_ | FA.property;
4913 enum safety = FA.safe | FA.trusted;
4914 enum ok =
4915 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) &&
4916 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) &&
4917 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
4918 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ;
4919 }
4920 /*
4921 * Check for return type: usual implicit convertion.
4922 */
4923 template checkReturnType()
4924 {
4925 enum ok = is(ReturnType!Upr : ReturnType!Lwr);
4926 }
4927 /*
4928 * Check for parameters:
4929 * - require exact match for types (cf. bugzilla 3075)
4930 * - require exact match for in, out, ref and lazy
4931 * - overrider can add scope, but can't remove
4932 */
4933 template checkParameters()
4934 {
4935 alias STC = ParameterStorageClass;
4936 alias UprParams = Parameters!Upr;
4937 alias LwrParams = Parameters!Lwr;
4938 alias UprPSTCs = ParameterStorageClassTuple!Upr;
4939 alias LwrPSTCs = ParameterStorageClassTuple!Lwr;
4940 //
4941 template checkNext(size_t i)
4942 {
4943 static if (i < UprParams.length)
4944 {
4945 enum uprStc = UprPSTCs[i];
4946 enum lwrStc = LwrPSTCs[i];
4947 //
4948 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
4949 enum ok =
4950 ((uprStc & wantExact ) == (lwrStc & wantExact )) &&
4951 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) &&
4952 checkNext!(i + 1).ok;
4953 }
4954 else
4955 enum ok = true; // done
4956 }
4957 static if (UprParams.length == LwrParams.length)
4958 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
4959 else
4960 enum ok = false;
4961 }
4962
4963 /* run all the checks */
4964 enum isCovariantWith =
4965 checkLinkage !().ok &&
4966 checkVariadicity!().ok &&
4967 checkSTC !().ok &&
4968 checkAttributes !().ok &&
4969 checkReturnType !().ok &&
4970 checkParameters !().ok ;
4971 }
4972 }
4973
4974 ///
4975 @safe unittest
4976 {
4977 interface I { I clone(); }
4978 interface J { J clone(); }
4979 class C : I
4980 {
4981 override C clone() // covariant overriding of I.clone()
4982 {
4983 return new C;
4984 }
4985 }
4986
4987 // C.clone() can override I.clone(), indeed.
4988 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
4989
4990 // C.clone() can't override J.clone(); the return type C is not implicitly
4991 // convertible to J.
4992 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
4993 }
4994
4995 @safe unittest
4996 {
4997 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
4998
4999 // covariant return type
5000 interface I {}
5001 interface J : I {}
5002 interface BaseA { const(I) test(int); }
5003 interface DerivA_1 : BaseA { override const(J) test(int); }
5004 interface DerivA_2 : BaseA { override J test(int); }
5005 static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5006 static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5007 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5008 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5009 static assert( isCovariantWith!(BaseA.test, BaseA.test));
5010 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5011 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5012
5013 // scope parameter
5014 interface BaseB { void test( int*, int*); }
5015 interface DerivB_1 : BaseB { override void test(scope int*, int*); }
5016 interface DerivB_2 : BaseB { override void test( int*, scope int*); }
5017 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5018 static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5019 static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5020 static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5021 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5022 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5023 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5024
5025 // function storage class
5026 interface BaseC { void test() ; }
5027 interface DerivC_1 : BaseC { override void test() const; }
5028 static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5029 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5030
5031 // increasing safety
5032 interface BaseE { void test() ; }
5033 interface DerivE_1 : BaseE { override void test() @safe ; }
5034 interface DerivE_2 : BaseE { override void test() @trusted; }
5035 static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5036 static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5037 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5038 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5039
5040 // @safe and @trusted
5041 interface BaseF
5042 {
5043 void test1() @safe;
5044 void test2() @trusted;
5045 }
5046 interface DerivF : BaseF
5047 {
5048 override void test1() @trusted;
5049 override void test2() @safe;
5050 }
5051 static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5052 static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5053 }
5054
5055
5056 // Needed for rvalueOf/lvalueOf because "inout on return means
5057 // inout must be on a parameter as well"
5058 private struct __InoutWorkaroundStruct{}
5059
5060 /**
5061 Creates an lvalue or rvalue of type $(D T) for $(D typeof(...)) and
5062 $(D __traits(compiles, ...)) purposes. No actual value is returned.
5063
5064 Note: Trying to use returned value will result in a
5065 "Symbol Undefined" error at link time.
5066
5067 Example:
5068 ---
5069 // Note that `f` doesn't have to be implemented
5070 // as is isn't called.
5071 int f(int);
5072 bool f(ref int);
5073 static assert(is(typeof(f(rvalueOf!int)) == int));
5074 static assert(is(typeof(f(lvalueOf!int)) == bool));
5075
5076 int i = rvalueOf!int; // error, no actual value is returned
5077 ---
5078 */
5079 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5080
5081 /// ditto
5082 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5083
5084 // Note: unittest can't be used as an example here as function overloads
5085 // aren't allowed inside functions.
5086
5087 @system unittest
5088 {
5089 void needLvalue(T)(ref T);
5090 static struct S { }
5091 int i;
5092 struct Nested { void f() { ++i; } }
5093 foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5094 {
5095 static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5096 static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5097 static assert(is(typeof(rvalueOf!T) == T));
5098 static assert(is(typeof(lvalueOf!T) == T));
5099 }
5100
5101 static assert(!__traits(compiles, rvalueOf!int = 1));
5102 static assert( __traits(compiles, lvalueOf!byte = 127));
5103 static assert(!__traits(compiles, lvalueOf!byte = 128));
5104 }
5105
5106
5107 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5108 // SomethingTypeOf
5109 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5110
5111 private template AliasThisTypeOf(T) if (isAggregateType!T)
5112 {
5113 alias members = AliasSeq!(__traits(getAliasThis, T));
5114
5115 static if (members.length == 1)
5116 {
5117 alias AliasThisTypeOf = typeof(__traits(getMember, T.init, members[0]));
5118 }
5119 else
5120 static assert(0, T.stringof~" does not have alias this type");
5121 }
5122
5123 /*
5124 */
5125 template BooleanTypeOf(T)
5126 {
5127 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5128 alias X = BooleanTypeOf!AT;
5129 else
5130 alias X = OriginalType!T;
5131
5132 static if (is(Unqual!X == bool))
5133 {
5134 alias BooleanTypeOf = X;
5135 }
5136 else
5137 static assert(0, T.stringof~" is not boolean type");
5138 }
5139
5140 @safe unittest
5141 {
5142 // unexpected failure, maybe dmd type-merging bug
5143 foreach (T; AliasSeq!bool)
5144 foreach (Q; TypeQualifierList)
5145 {
5146 static assert( is(Q!T == BooleanTypeOf!( Q!T )));
5147 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5148 }
5149
5150 foreach (T; AliasSeq!(void, NumericTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList))
5151 foreach (Q; TypeQualifierList)
5152 {
5153 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof);
5154 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5155 }
5156 }
5157
5158 @safe unittest
5159 {
5160 struct B
5161 {
5162 bool val;
5163 alias val this;
5164 }
5165 struct S
5166 {
5167 B b;
5168 alias b this;
5169 }
5170 static assert(is(BooleanTypeOf!B == bool));
5171 static assert(is(BooleanTypeOf!S == bool));
5172 }
5173
5174 /*
5175 */
5176 template IntegralTypeOf(T)
5177 {
5178 import std.meta : staticIndexOf;
5179 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5180 alias X = IntegralTypeOf!AT;
5181 else
5182 alias X = OriginalType!T;
5183
5184 static if (staticIndexOf!(Unqual!X, IntegralTypeList) >= 0)
5185 {
5186 alias IntegralTypeOf = X;
5187 }
5188 else
5189 static assert(0, T.stringof~" is not an integral type");
5190 }
5191
5192 @safe unittest
5193 {
5194 foreach (T; IntegralTypeList)
5195 foreach (Q; TypeQualifierList)
5196 {
5197 static assert( is(Q!T == IntegralTypeOf!( Q!T )));
5198 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5199 }
5200
5201 foreach (T; AliasSeq!(void, bool, FloatingPointTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList))
5202 foreach (Q; TypeQualifierList)
5203 {
5204 static assert(!is(IntegralTypeOf!( Q!T )));
5205 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5206 }
5207 }
5208
5209 /*
5210 */
5211 template FloatingPointTypeOf(T)
5212 {
5213 import std.meta : staticIndexOf;
5214 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5215 alias X = FloatingPointTypeOf!AT;
5216 else
5217 alias X = OriginalType!T;
5218
5219 static if (staticIndexOf!(Unqual!X, FloatingPointTypeList) >= 0)
5220 {
5221 alias FloatingPointTypeOf = X;
5222 }
5223 else
5224 static assert(0, T.stringof~" is not a floating point type");
5225 }
5226
5227 @safe unittest
5228 {
5229 foreach (T; FloatingPointTypeList)
5230 foreach (Q; TypeQualifierList)
5231 {
5232 static assert( is(Q!T == FloatingPointTypeOf!( Q!T )));
5233 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5234 }
5235
5236 foreach (T; AliasSeq!(void, bool, IntegralTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList))
5237 foreach (Q; TypeQualifierList)
5238 {
5239 static assert(!is(FloatingPointTypeOf!( Q!T )));
5240 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5241 }
5242 }
5243
5244 /*
5245 */
5246 template NumericTypeOf(T)
5247 {
5248 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5249 {
5250 alias NumericTypeOf = X;
5251 }
5252 else
5253 static assert(0, T.stringof~" is not a numeric type");
5254 }
5255
5256 @safe unittest
5257 {
5258 foreach (T; NumericTypeList)
5259 foreach (Q; TypeQualifierList)
5260 {
5261 static assert( is(Q!T == NumericTypeOf!( Q!T )));
5262 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5263 }
5264
5265 foreach (T; AliasSeq!(void, bool, CharTypeList, ImaginaryTypeList, ComplexTypeList))
5266 foreach (Q; TypeQualifierList)
5267 {
5268 static assert(!is(NumericTypeOf!( Q!T )));
5269 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5270 }
5271 }
5272
5273 /*
5274 */
5275 template UnsignedTypeOf(T)
5276 {
5277 import std.meta : staticIndexOf;
5278 static if (is(IntegralTypeOf!T X) &&
5279 staticIndexOf!(Unqual!X, UnsignedIntTypeList) >= 0)
5280 alias UnsignedTypeOf = X;
5281 else
5282 static assert(0, T.stringof~" is not an unsigned type.");
5283 }
5284
5285 /*
5286 */
5287 template SignedTypeOf(T)
5288 {
5289 import std.meta : staticIndexOf;
5290 static if (is(IntegralTypeOf!T X) &&
5291 staticIndexOf!(Unqual!X, SignedIntTypeList) >= 0)
5292 alias SignedTypeOf = X;
5293 else static if (is(FloatingPointTypeOf!T X))
5294 alias SignedTypeOf = X;
5295 else
5296 static assert(0, T.stringof~" is not an signed type.");
5297 }
5298
5299 /*
5300 */
5301 template CharTypeOf(T)
5302 {
5303 import std.meta : staticIndexOf;
5304 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5305 alias X = CharTypeOf!AT;
5306 else
5307 alias X = OriginalType!T;
5308
5309 static if (staticIndexOf!(Unqual!X, CharTypeList) >= 0)
5310 {
5311 alias CharTypeOf = X;
5312 }
5313 else
5314 static assert(0, T.stringof~" is not a character type");
5315 }
5316
5317 @safe unittest
5318 {
5319 foreach (T; CharTypeList)
5320 foreach (Q; TypeQualifierList)
5321 {
5322 static assert( is(CharTypeOf!( Q!T )));
5323 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5324 }
5325
5326 foreach (T; AliasSeq!(void, bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList))
5327 foreach (Q; TypeQualifierList)
5328 {
5329 static assert(!is(CharTypeOf!( Q!T )));
5330 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5331 }
5332
5333 foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5334 foreach (Q; TypeQualifierList)
5335 {
5336 static assert(!is(CharTypeOf!( Q!T )));
5337 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5338 }
5339 }
5340
5341 /*
5342 */
5343 template StaticArrayTypeOf(T)
5344 {
5345 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5346 alias X = StaticArrayTypeOf!AT;
5347 else
5348 alias X = OriginalType!T;
5349
5350 static if (is(X : E[n], E, size_t n))
5351 alias StaticArrayTypeOf = X;
5352 else
5353 static assert(0, T.stringof~" is not a static array type");
5354 }
5355
5356 @safe unittest
5357 {
5358 foreach (T; AliasSeq!(bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList))
5359 foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5360 {
5361 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) ));
5362
5363 foreach (P; TypeQualifierList)
5364 { // SubTypeOf cannot have inout type
5365 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
5366 }
5367 }
5368
5369 foreach (T; AliasSeq!void)
5370 foreach (Q; AliasSeq!TypeQualifierList)
5371 {
5372 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
5373 }
5374 }
5375
5376 /*
5377 */
5378 template DynamicArrayTypeOf(T)
5379 {
5380 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5381 alias X = DynamicArrayTypeOf!AT;
5382 else
5383 alias X = OriginalType!T;
5384
5385 static if (is(Unqual!X : E[], E) && !is(typeof({ enum n = X.length; })))
5386 {
5387 alias DynamicArrayTypeOf = X;
5388 }
5389 else
5390 static assert(0, T.stringof~" is not a dynamic array");
5391 }
5392
5393 @safe unittest
5394 {
5395 foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList))
5396 foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5397 {
5398 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) ));
5399 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) ));
5400
5401 foreach (P; AliasSeq!(MutableOf, ConstOf, ImmutableOf))
5402 {
5403 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
5404 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
5405 }
5406 }
5407
5408 static assert(!is(DynamicArrayTypeOf!(int[3])));
5409 static assert(!is(DynamicArrayTypeOf!(void[3])));
5410 static assert(!is(DynamicArrayTypeOf!(typeof(null))));
5411 }
5412
5413 /*
5414 */
5415 template ArrayTypeOf(T)
5416 {
5417 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
5418 {
5419 alias ArrayTypeOf = X;
5420 }
5421 else
5422 static assert(0, T.stringof~" is not an array type");
5423 }
5424
5425 /*
5426 Always returns the Dynamic Array version.
5427 */
5428 template StringTypeOf(T)
5429 {
5430 static if (is(T == typeof(null)))
5431 {
5432 // It is impossible to determine exact string type from typeof(null) -
5433 // it means that StringTypeOf!(typeof(null)) is undefined.
5434 // Then this behavior is convenient for template constraint.
5435 static assert(0, T.stringof~" is not a string type");
5436 }
5437 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
5438 {
5439 static if (is(T : U[], U))
5440 alias StringTypeOf = U[];
5441 else
5442 static assert(0);
5443 }
5444 else
5445 static assert(0, T.stringof~" is not a string type");
5446 }
5447
5448 @safe unittest
5449 {
5450 foreach (T; CharTypeList)
5451 foreach (Q; AliasSeq!(MutableOf, ConstOf, ImmutableOf, InoutOf))
5452 {
5453 static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
5454
5455 static if (!__traits(isSame, Q, InoutOf))
5456 {
5457 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
5458
5459 alias Str = Q!T[];
5460 class C(S) { S val; alias val this; }
5461 static assert(is(StringTypeOf!(C!Str) == Str));
5462 }
5463 }
5464
5465 foreach (T; CharTypeList)
5466 foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
5467 {
5468 static assert(!is(StringTypeOf!( Q!T[] )));
5469 }
5470 }
5471
5472 @safe unittest
5473 {
5474 static assert(is(StringTypeOf!(char[4]) == char[]));
5475 }
5476
5477 /*
5478 */
5479 template AssocArrayTypeOf(T)
5480 {
5481 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
5482 alias X = AssocArrayTypeOf!AT;
5483 else
5484 alias X = OriginalType!T;
5485
5486 static if (is(Unqual!X : V[K], K, V))
5487 {
5488 alias AssocArrayTypeOf = X;
5489 }
5490 else
5491 static assert(0, T.stringof~" is not an associative array type");
5492 }
5493
5494 @safe unittest
5495 {
5496 foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
5497 foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5498 foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5499 foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5500 {
5501 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) ));
5502 }
5503
5504 foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
5505 foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5506 foreach (P; AliasSeq!TypeQualifierList)
5507 foreach (Q; AliasSeq!TypeQualifierList)
5508 foreach (R; AliasSeq!TypeQualifierList)
5509 {
5510 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
5511 }
5512 }
5513
5514 /*
5515 */
5516 template BuiltinTypeOf(T)
5517 {
5518 static if (is(T : void)) alias BuiltinTypeOf = void;
5519 else static if (is(BooleanTypeOf!T X)) alias BuiltinTypeOf = X;
5520 else static if (is(IntegralTypeOf!T X)) alias BuiltinTypeOf = X;
5521 else static if (is(FloatingPointTypeOf!T X))alias BuiltinTypeOf = X;
5522 else static if (is(T : const(ireal))) alias BuiltinTypeOf = ireal; //TODO
5523 else static if (is(T : const(creal))) alias BuiltinTypeOf = creal; //TODO
5524 else static if (is(CharTypeOf!T X)) alias BuiltinTypeOf = X;
5525 else static if (is(ArrayTypeOf!T X)) alias BuiltinTypeOf = X;
5526 else static if (is(AssocArrayTypeOf!T X)) alias BuiltinTypeOf = X;
5527 else static assert(0);
5528 }
5529
5530 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5531 // isSomething
5532 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5533
5534 /**
5535 * Detect whether $(D T) is a built-in boolean type.
5536 */
5537 enum bool isBoolean(T) = is(BooleanTypeOf!T) && !isAggregateType!T;
5538
5539 ///
5540 @safe unittest
5541 {
5542 static assert( isBoolean!bool);
5543 enum EB : bool { a = true }
5544 static assert( isBoolean!EB);
5545 static assert(!isBoolean!(SubTypeOf!bool));
5546 }
5547
5548 @safe unittest
5549 {
5550 static struct S(T)
5551 {
5552 T t;
5553 alias t this;
5554 }
5555 static assert(!isIntegral!(S!bool));
5556 }
5557
5558 /**
5559 * Detect whether $(D T) is a built-in integral type. Types $(D bool),
5560 * $(D char), $(D wchar), and $(D dchar) are not considered integral.
5561 */
5562 enum bool isIntegral(T) = is(IntegralTypeOf!T) && !isAggregateType!T;
5563
5564 ///
5565 @safe unittest
5566 {
5567 static assert(
5568 isIntegral!byte &&
5569 isIntegral!short &&
5570 isIntegral!int &&
5571 isIntegral!long &&
5572 isIntegral!(const(long)) &&
5573 isIntegral!(immutable(long))
5574 );
5575
5576 static assert(
5577 !isIntegral!bool &&
5578 !isIntegral!char &&
5579 !isIntegral!double
5580 );
5581
5582 // types which act as integral values do not pass
5583 struct S
5584 {
5585 int val;
5586 alias val this;
5587 }
5588
5589 static assert(!isIntegral!S);
5590 }
5591
5592 @safe unittest
5593 {
5594 foreach (T; IntegralTypeList)
5595 {
5596 foreach (Q; TypeQualifierList)
5597 {
5598 static assert( isIntegral!(Q!T));
5599 static assert(!isIntegral!(SubTypeOf!(Q!T)));
5600 }
5601 }
5602
5603 static assert(!isIntegral!float);
5604
5605 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
5606 enum EI : int { a = -1, b = 0, c = 1 } // base type is signed (bug 7909)
5607 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU);
5608 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI);
5609 }
5610
5611 /**
5612 * Detect whether $(D T) is a built-in floating point type.
5613 */
5614 enum bool isFloatingPoint(T) = __traits(isFloating, T) && !(is(Unqual!T == cfloat) ||
5615 is(Unqual!T == cdouble) ||
5616 is(Unqual!T == creal) ||
5617 is(Unqual!T == ifloat) ||
5618 is(Unqual!T == idouble) ||
5619 is(Unqual!T == ireal));
5620
5621 ///
5622 @safe unittest
5623 {
5624 static assert(
5625 isFloatingPoint!float &&
5626 isFloatingPoint!double &&
5627 isFloatingPoint!real &&
5628 isFloatingPoint!(const(real)) &&
5629 isFloatingPoint!(immutable(real))
5630 );
5631
5632 static assert(!isFloatingPoint!int);
5633
5634 // complex and imaginary numbers do not pass
5635 static assert(
5636 !isFloatingPoint!cfloat &&
5637 !isFloatingPoint!ifloat
5638 );
5639
5640 // types which act as floating point values do not pass
5641 struct S
5642 {
5643 float val;
5644 alias val this;
5645 }
5646
5647 static assert(!isFloatingPoint!S);
5648 }
5649
5650 @safe unittest
5651 {
5652 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
5653
5654 foreach (T; AliasSeq!(FloatingPointTypeList, EF))
5655 {
5656 foreach (Q; TypeQualifierList)
5657 {
5658 static assert( isFloatingPoint!(Q!T));
5659 static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
5660 }
5661 }
5662 foreach (T; IntegralTypeList)
5663 {
5664 foreach (Q; TypeQualifierList)
5665 {
5666 static assert(!isFloatingPoint!(Q!T));
5667 }
5668 }
5669 }
5670
5671 // https://issues.dlang.org/show_bug.cgi?id=17195
5672 @safe unittest
5673 {
5674 static assert(!isFloatingPoint!cfloat);
5675 static assert(!isFloatingPoint!cdouble);
5676 static assert(!isFloatingPoint!creal);
5677
5678 static assert(!isFloatingPoint!ifloat);
5679 static assert(!isFloatingPoint!idouble);
5680 static assert(!isFloatingPoint!ireal);
5681 }
5682
5683 /**
5684 * Detect whether $(D T) is a built-in numeric type (integral or floating
5685 * point).
5686 */
5687 enum bool isNumeric(T) = __traits(isArithmetic, T) && !(is(Unqual!T == bool) ||
5688 is(Unqual!T == char) ||
5689 is(Unqual!T == wchar) ||
5690 is(Unqual!T == dchar));
5691
5692 ///
5693 @safe unittest
5694 {
5695 static assert(
5696 isNumeric!byte &&
5697 isNumeric!short &&
5698 isNumeric!int &&
5699 isNumeric!long &&
5700 isNumeric!float &&
5701 isNumeric!double &&
5702 isNumeric!real &&
5703 isNumeric!(const(real)) &&
5704 isNumeric!(immutable(real))
5705 );
5706
5707 static assert(
5708 !isNumeric!void &&
5709 !isNumeric!bool &&
5710 !isNumeric!char &&
5711 !isNumeric!wchar &&
5712 !isNumeric!dchar
5713 );
5714
5715 // types which act as numeric values do not pass
5716 struct S
5717 {
5718 int val;
5719 alias val this;
5720 }
5721
5722 static assert(!isIntegral!S);
5723 }
5724
5725 @safe unittest
5726 {
5727 foreach (T; AliasSeq!(NumericTypeList))
5728 {
5729 foreach (Q; TypeQualifierList)
5730 {
5731 static assert( isNumeric!(Q!T));
5732 static assert(!isNumeric!(SubTypeOf!(Q!T)));
5733 }
5734 }
5735
5736 static struct S(T)
5737 {
5738 T t;
5739 alias t this;
5740 }
5741 static assert(!isNumeric!(S!int));
5742 }
5743
5744 /**
5745 * Detect whether $(D T) is a scalar type (a built-in numeric, character or
5746 * boolean type).
5747 */
5748 enum bool isScalarType(T) = is(T : real) && !isAggregateType!T;
5749
5750 ///
5751 @safe unittest
5752 {
5753 static assert(!isScalarType!void);
5754 static assert( isScalarType!(immutable(byte)));
5755 static assert( isScalarType!(immutable(ushort)));
5756 static assert( isScalarType!(immutable(int)));
5757 static assert( isScalarType!(ulong));
5758 static assert( isScalarType!(shared(float)));
5759 static assert( isScalarType!(shared(const bool)));
5760 static assert( isScalarType!(const(char)));
5761 static assert( isScalarType!(wchar));
5762 static assert( isScalarType!(const(dchar)));
5763 static assert( isScalarType!(const(double)));
5764 static assert( isScalarType!(const(real)));
5765 }
5766
5767 @safe unittest
5768 {
5769 static struct S(T)
5770 {
5771 T t;
5772 alias t this;
5773 }
5774 static assert(!isScalarType!(S!int));
5775 }
5776
5777 /**
5778 * Detect whether $(D T) is a basic type (scalar type or void).
5779 */
5780 enum bool isBasicType(T) = isScalarType!T || is(Unqual!T == void);
5781
5782 ///
5783 @safe unittest
5784 {
5785 static assert(isBasicType!void);
5786 static assert(isBasicType!(const(void)));
5787 static assert(isBasicType!(shared(void)));
5788 static assert(isBasicType!(immutable(void)));
5789 static assert(isBasicType!(shared const(void)));
5790 static assert(isBasicType!(shared inout(void)));
5791 static assert(isBasicType!(shared inout const(void)));
5792 static assert(isBasicType!(inout(void)));
5793 static assert(isBasicType!(inout const(void)));
5794 static assert(isBasicType!(immutable(int)));
5795 static assert(isBasicType!(shared(float)));
5796 static assert(isBasicType!(shared(const bool)));
5797 static assert(isBasicType!(const(dchar)));
5798 }
5799
5800 /**
5801 * Detect whether $(D T) is a built-in unsigned numeric type.
5802 */
5803 enum bool isUnsigned(T) = __traits(isUnsigned, T) && !(is(Unqual!T == char) ||
5804 is(Unqual!T == wchar) ||
5805 is(Unqual!T == dchar) ||
5806 is(Unqual!T == bool));
5807
5808 ///
5809 @safe unittest
5810 {
5811 static assert(
5812 isUnsigned!uint &&
5813 isUnsigned!ulong
5814 );
5815
5816 static assert(
5817 !isUnsigned!char &&
5818 !isUnsigned!int &&
5819 !isUnsigned!long &&
5820 !isUnsigned!char &&
5821 !isUnsigned!wchar &&
5822 !isUnsigned!dchar
5823 );
5824 }
5825
5826 @safe unittest
5827 {
5828 foreach (T; AliasSeq!(UnsignedIntTypeList))
5829 {
5830 foreach (Q; TypeQualifierList)
5831 {
5832 static assert( isUnsigned!(Q!T));
5833 static assert(!isUnsigned!(SubTypeOf!(Q!T)));
5834 }
5835 }
5836
5837 static struct S(T)
5838 {
5839 T t;
5840 alias t this;
5841 }
5842 static assert(!isUnsigned!(S!uint));
5843 }
5844
5845 /**
5846 * Detect whether $(D T) is a built-in signed numeric type.
5847 */
5848 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T);
5849
5850 ///
5851 @safe unittest
5852 {
5853 static assert(
5854 isSigned!int &&
5855 isSigned!long
5856 );
5857
5858 static assert(
5859 !isSigned!uint &&
5860 !isSigned!ulong
5861 );
5862 }
5863
5864 @safe unittest
5865 {
5866 enum E { e1 = 0 }
5867 static assert(isSigned!E);
5868
5869 enum Eubyte : ubyte { e1 = 0 }
5870 static assert(!isSigned!Eubyte);
5871
5872 foreach (T; AliasSeq!(SignedIntTypeList))
5873 {
5874 foreach (Q; TypeQualifierList)
5875 {
5876 static assert( isSigned!(Q!T));
5877 static assert(!isSigned!(SubTypeOf!(Q!T)));
5878 }
5879 }
5880
5881 static struct S(T)
5882 {
5883 T t;
5884 alias t this;
5885 }
5886 static assert(!isSigned!(S!uint));
5887 }
5888
5889 // https://issues.dlang.org/show_bug.cgi?id=17196
5890 @safe unittest
5891 {
5892 static assert(isUnsigned!bool == false);
5893 static assert(isSigned!bool == false);
5894 }
5895
5896 /**
5897 * Detect whether $(D T) is one of the built-in character types.
5898 *
5899 * The built-in char types are any of $(D char), $(D wchar) or $(D dchar), with
5900 * or without qualifiers.
5901 */
5902 enum bool isSomeChar(T) = is(CharTypeOf!T) && !isAggregateType!T;
5903
5904 ///
5905 @safe unittest
5906 {
5907 //Char types
5908 static assert( isSomeChar!char);
5909 static assert( isSomeChar!wchar);
5910 static assert( isSomeChar!dchar);
5911 static assert( isSomeChar!(typeof('c')));
5912 static assert( isSomeChar!(immutable char));
5913 static assert( isSomeChar!(const dchar));
5914
5915 //Non char types
5916 static assert(!isSomeChar!int);
5917 static assert(!isSomeChar!byte);
5918 static assert(!isSomeChar!string);
5919 static assert(!isSomeChar!wstring);
5920 static assert(!isSomeChar!dstring);
5921 static assert(!isSomeChar!(char[4]));
5922 }
5923
5924 @safe unittest
5925 {
5926 enum EC : char { a = 'x', b = 'y' }
5927
5928 foreach (T; AliasSeq!(CharTypeList, EC))
5929 {
5930 foreach (Q; TypeQualifierList)
5931 {
5932 static assert( isSomeChar!( Q!T ));
5933 static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
5934 }
5935 }
5936
5937 // alias-this types are not allowed
5938 static struct S(T)
5939 {
5940 T t;
5941 alias t this;
5942 }
5943 static assert(!isSomeChar!(S!char));
5944 }
5945
5946 /**
5947 Detect whether $(D T) is one of the built-in string types.
5948
5949 The built-in string types are $(D Char[]), where $(D Char) is any of $(D char),
5950 $(D wchar) or $(D dchar), with or without qualifiers.
5951
5952 Static arrays of characters (like $(D char[80])) are not considered
5953 built-in string types.
5954 */
5955 enum bool isSomeString(T) = is(StringTypeOf!T) && !isAggregateType!T && !isStaticArray!T;
5956
5957 ///
5958 @safe unittest
5959 {
5960 //String types
5961 static assert( isSomeString!string);
5962 static assert( isSomeString!(wchar[]));
5963 static assert( isSomeString!(dchar[]));
5964 static assert( isSomeString!(typeof("aaa")));
5965 static assert( isSomeString!(const(char)[]));
5966
5967 enum ES : string { a = "aaa", b = "bbb" }
5968 static assert( isSomeString!ES);
5969
5970 //Non string types
5971 static assert(!isSomeString!int);
5972 static assert(!isSomeString!(int[]));
5973 static assert(!isSomeString!(byte[]));
5974 static assert(!isSomeString!(typeof(null)));
5975 static assert(!isSomeString!(char[4]));
5976 }
5977
5978 @safe unittest
5979 {
5980 foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
5981 {
5982 static assert( isSomeString!( T ));
5983 static assert(!isSomeString!(SubTypeOf!(T)));
5984 }
5985 }
5986
5987 /**
5988 * Detect whether type $(D T) is a narrow string.
5989 *
5990 * All arrays that use char, wchar, and their qualified versions are narrow
5991 * strings. (Those include string and wstring).
5992 */
5993 enum bool isNarrowString(T) = (is(T : const char[]) || is(T : const wchar[])) && !isAggregateType!T && !isStaticArray!T;
5994
5995 ///
5996 @safe unittest
5997 {
5998 static assert(isNarrowString!string);
5999 static assert(isNarrowString!wstring);
6000 static assert(isNarrowString!(char[]));
6001 static assert(isNarrowString!(wchar[]));
6002
6003 static assert(!isNarrowString!dstring);
6004 static assert(!isNarrowString!(dchar[]));
6005 }
6006
6007 @safe unittest
6008 {
6009 foreach (T; AliasSeq!(char[], string, wstring))
6010 {
6011 foreach (Q; AliasSeq!(MutableOf, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6012 {
6013 static assert( isNarrowString!( Q!T ));
6014 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6015 }
6016 }
6017
6018 foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6019 {
6020 foreach (Q; TypeQualifierList)
6021 {
6022 static assert(!isNarrowString!( Q!T ));
6023 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6024 }
6025 }
6026 }
6027
6028 /**
6029 * Detects whether `T` is a comparable type. Basic types and structs and
6030 * classes that implement opCmp are ordering comparable.
6031 */
6032 enum bool isOrderingComparable(T) = ifTestable!(T, unaryFun!"a < a");
6033
6034 ///
6035 @safe unittest
6036 {
6037 static assert(isOrderingComparable!int);
6038 static assert(isOrderingComparable!string);
6039 static assert(!isOrderingComparable!creal);
6040
6041 static struct Foo {}
6042 static assert(!isOrderingComparable!Foo);
6043
6044 static struct Bar
6045 {
6046 int a;
6047 auto opCmp(Bar b1) const { return a - b1.a; }
6048 }
6049
6050 Bar b1 = Bar(5);
6051 Bar b2 = Bar(7);
6052 assert(isOrderingComparable!Bar && b2 > b1);
6053 }
6054
6055 /// ditto
6056 enum bool isEqualityComparable(T) = ifTestable!(T, unaryFun!"a == a");
6057
6058 @safe unittest
6059 {
6060 static assert(isEqualityComparable!int);
6061 static assert(isEqualityComparable!string);
6062 static assert(isEqualityComparable!creal);
6063 static assert(!isEqualityComparable!void);
6064
6065 struct Foo {}
6066 static assert(isEqualityComparable!Foo);
6067
6068 struct Bar
6069 {
6070 int a;
6071 auto opEquals(Bar b1) const { return a == b1.a; }
6072 }
6073
6074 Bar b1 = Bar(5);
6075 Bar b2 = Bar(5);
6076 Bar b3 = Bar(7);
6077 static assert(isEqualityComparable!Bar);
6078 assert(b1 == b2);
6079 assert(b1 != b3);
6080 }
6081
6082 /**
6083 * Detect whether $(D T) is a struct, static array, or enum that is implicitly
6084 * convertible to a string.
6085 */
6086 template isConvertibleToString(T)
6087 {
6088 enum isConvertibleToString =
6089 (isAggregateType!T || isStaticArray!T || is(T == enum))
6090 && is(StringTypeOf!T);
6091 }
6092
6093 ///
6094 @safe unittest
6095 {
6096 static struct AliasedString
6097 {
6098 string s;
6099 alias s this;
6100 }
6101
6102 enum StringEnum { a = "foo" }
6103
6104 assert(!isConvertibleToString!string);
6105 assert(isConvertibleToString!AliasedString);
6106 assert(isConvertibleToString!StringEnum);
6107 assert(isConvertibleToString!(char[25]));
6108 assert(!isConvertibleToString!(char[]));
6109 }
6110
6111 @safe unittest // Bugzilla 16573
6112 {
6113 enum I : int { foo = 1 }
6114 enum S : string { foo = "foo" }
6115 assert(!isConvertibleToString!I);
6116 assert(isConvertibleToString!S);
6117 }
6118
6119 package template convertToString(T)
6120 {
6121 static if (isConvertibleToString!T)
6122 alias convertToString = StringTypeOf!T;
6123 else
6124 alias convertToString = T;
6125 }
6126
6127 /**
6128 * Detect whether type $(D T) is a string that will be autodecoded.
6129 *
6130 * All arrays that use char, wchar, and their qualified versions are narrow
6131 * strings. (Those include string and wstring).
6132 * Aggregates that implicitly cast to narrow strings are included.
6133 *
6134 * Params:
6135 * T = type to be tested
6136 *
6137 * Returns:
6138 * true if T represents a string that is subject to autodecoding
6139 *
6140 * See Also:
6141 * $(LREF isNarrowString)
6142 */
6143 enum bool isAutodecodableString(T) = (is(T : const char[]) || is(T : const wchar[])) && !isStaticArray!T;
6144
6145 ///
6146 @safe unittest
6147 {
6148 static struct Stringish
6149 {
6150 string s;
6151 alias s this;
6152 }
6153 assert(isAutodecodableString!wstring);
6154 assert(isAutodecodableString!Stringish);
6155 assert(!isAutodecodableString!dstring);
6156 }
6157
6158 /**
6159 * Detect whether type $(D T) is a static array.
6160 */
6161 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6162
6163 ///
6164 @safe unittest
6165 {
6166 static assert( isStaticArray!(int[3]));
6167 static assert( isStaticArray!(const(int)[5]));
6168 static assert( isStaticArray!(const(int)[][5]));
6169
6170 static assert(!isStaticArray!(const(int)[]));
6171 static assert(!isStaticArray!(immutable(int)[]));
6172 static assert(!isStaticArray!(const(int)[4][]));
6173 static assert(!isStaticArray!(int[]));
6174 static assert(!isStaticArray!(int[char]));
6175 static assert(!isStaticArray!(int[1][]));
6176 static assert(!isStaticArray!(int[int]));
6177 static assert(!isStaticArray!int);
6178 }
6179
6180 @safe unittest
6181 {
6182 foreach (T; AliasSeq!(int[51], int[][2],
6183 char[][int][11], immutable char[13u],
6184 const(real)[1], const(real)[1][1], void[0]))
6185 {
6186 foreach (Q; TypeQualifierList)
6187 {
6188 static assert( isStaticArray!( Q!T ));
6189 static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
6190 }
6191 }
6192
6193 //enum ESA : int[1] { a = [1], b = [2] }
6194 //static assert( isStaticArray!ESA);
6195 }
6196
6197 /**
6198 * Detect whether type $(D T) is a dynamic array.
6199 */
6200 enum bool isDynamicArray(T) = is(DynamicArrayTypeOf!T) && !isAggregateType!T;
6201
6202 ///
6203 @safe unittest
6204 {
6205 static assert( isDynamicArray!(int[]));
6206 static assert( isDynamicArray!(string));
6207 static assert( isDynamicArray!(long[3][]));
6208
6209 static assert(!isDynamicArray!(int[5]));
6210 static assert(!isDynamicArray!(typeof(null)));
6211 }
6212
6213 @safe unittest
6214 {
6215 import std.meta : AliasSeq;
6216 foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
6217 {
6218 foreach (Q; TypeQualifierList)
6219 {
6220 static assert( isDynamicArray!( Q!T ));
6221 static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
6222 }
6223 }
6224 }
6225
6226 /**
6227 * Detect whether type $(D T) is an array (static or dynamic; for associative
6228 * arrays see $(LREF isAssociativeArray)).
6229 */
6230 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
6231
6232 ///
6233 @safe unittest
6234 {
6235 static assert( isArray!(int[]));
6236 static assert( isArray!(int[5]));
6237 static assert( isArray!(string));
6238
6239 static assert(!isArray!uint);
6240 static assert(!isArray!(uint[uint]));
6241 static assert(!isArray!(typeof(null)));
6242 }
6243
6244 @safe unittest
6245 {
6246 import std.meta : AliasSeq;
6247 foreach (T; AliasSeq!(int[], int[5], void[]))
6248 {
6249 foreach (Q; TypeQualifierList)
6250 {
6251 static assert( isArray!(Q!T));
6252 static assert(!isArray!(SubTypeOf!(Q!T)));
6253 }
6254 }
6255 }
6256
6257 /**
6258 * Detect whether $(D T) is an associative array type
6259 */
6260 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
6261
6262 @safe unittest
6263 {
6264 struct Foo
6265 {
6266 @property uint[] keys() { return null; }
6267 @property uint[] values() { return null; }
6268 }
6269
6270 foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
6271 {
6272 foreach (Q; TypeQualifierList)
6273 {
6274 static assert( isAssociativeArray!(Q!T));
6275 static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
6276 }
6277 }
6278
6279 static assert(!isAssociativeArray!Foo);
6280 static assert(!isAssociativeArray!int);
6281 static assert(!isAssociativeArray!(int[]));
6282 static assert(!isAssociativeArray!(typeof(null)));
6283
6284 //enum EAA : int[int] { a = [1:1], b = [2:2] }
6285 //static assert( isAssociativeArray!EAA);
6286 }
6287
6288 /**
6289 * Detect whether type $(D T) is a builtin type.
6290 */
6291 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
6292
6293 ///
6294 @safe unittest
6295 {
6296 class C;
6297 union U;
6298 struct S;
6299 interface I;
6300
6301 static assert( isBuiltinType!void);
6302 static assert( isBuiltinType!string);
6303 static assert( isBuiltinType!(int[]));
6304 static assert( isBuiltinType!(C[string]));
6305 static assert(!isBuiltinType!C);
6306 static assert(!isBuiltinType!U);
6307 static assert(!isBuiltinType!S);
6308 static assert(!isBuiltinType!I);
6309 static assert(!isBuiltinType!(void delegate(int)));
6310 }
6311
6312 /**
6313 * Detect whether type $(D T) is a SIMD vector type.
6314 */
6315 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
6316
6317 @safe unittest
6318 {
6319 static if (is(__vector(float[4])))
6320 {
6321 alias SimdVec = __vector(float[4]);
6322 static assert(isSIMDVector!(__vector(float[4])));
6323 static assert(isSIMDVector!SimdVec);
6324 }
6325 static assert(!isSIMDVector!uint);
6326 static assert(!isSIMDVector!(float[4]));
6327 }
6328
6329 /**
6330 * Detect whether type $(D T) is a pointer.
6331 */
6332 enum bool isPointer(T) = is(T == U*, U) && !isAggregateType!T;
6333
6334 @safe unittest
6335 {
6336 foreach (T; AliasSeq!(int*, void*, char[]*))
6337 {
6338 foreach (Q; TypeQualifierList)
6339 {
6340 static assert( isPointer!(Q!T));
6341 static assert(!isPointer!(SubTypeOf!(Q!T)));
6342 }
6343 }
6344
6345 static assert(!isPointer!uint);
6346 static assert(!isPointer!(uint[uint]));
6347 static assert(!isPointer!(char[]));
6348 static assert(!isPointer!(typeof(null)));
6349 }
6350
6351 /**
6352 Returns the target type of a pointer.
6353 */
6354 alias PointerTarget(T : T*) = T;
6355
6356 ///
6357 @safe unittest
6358 {
6359 static assert(is(PointerTarget!(int*) == int));
6360 static assert(is(PointerTarget!(void*) == void));
6361 }
6362
6363 /**
6364 * Detect whether type $(D T) is an aggregate type.
6365 */
6366 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
6367 is(T == class) || is(T == interface);
6368
6369 ///
6370 @safe unittest
6371 {
6372 class C;
6373 union U;
6374 struct S;
6375 interface I;
6376
6377 static assert( isAggregateType!C);
6378 static assert( isAggregateType!U);
6379 static assert( isAggregateType!S);
6380 static assert( isAggregateType!I);
6381 static assert(!isAggregateType!void);
6382 static assert(!isAggregateType!string);
6383 static assert(!isAggregateType!(int[]));
6384 static assert(!isAggregateType!(C[string]));
6385 static assert(!isAggregateType!(void delegate(int)));
6386 }
6387
6388 /**
6389 * Returns $(D true) if T can be iterated over using a $(D foreach) loop with
6390 * a single loop variable of automatically inferred type, regardless of how
6391 * the $(D foreach) loop is implemented. This includes ranges, structs/classes
6392 * that define $(D opApply) with a single loop variable, and builtin dynamic,
6393 * static and associative arrays.
6394 */
6395 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
6396
6397 ///
6398 @safe unittest
6399 {
6400 struct OpApply
6401 {
6402 int opApply(scope int delegate(ref uint) dg) { assert(0); }
6403 }
6404
6405 struct Range
6406 {
6407 @property uint front() { assert(0); }
6408 void popFront() { assert(0); }
6409 enum bool empty = false;
6410 }
6411
6412 static assert( isIterable!(uint[]));
6413 static assert( isIterable!OpApply);
6414 static assert( isIterable!(uint[string]));
6415 static assert( isIterable!Range);
6416
6417 static assert(!isIterable!uint);
6418 }
6419
6420 /**
6421 * Returns true if T is not const or immutable. Note that isMutable is true for
6422 * string, or immutable(char)[], because the 'head' is mutable.
6423 */
6424 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
6425
6426 ///
6427 @safe unittest
6428 {
6429 static assert( isMutable!int);
6430 static assert( isMutable!string);
6431 static assert( isMutable!(shared int));
6432 static assert( isMutable!(shared const(int)[]));
6433
6434 static assert(!isMutable!(const int));
6435 static assert(!isMutable!(inout int));
6436 static assert(!isMutable!(shared(const int)));
6437 static assert(!isMutable!(shared(inout int)));
6438 static assert(!isMutable!(immutable string));
6439 }
6440
6441 /**
6442 * Returns true if T is an instance of the template S.
6443 */
6444 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
6445 /// ditto
6446 template isInstanceOf(alias S, alias T)
6447 {
6448 enum impl(alias T : S!Args, Args...) = true;
6449 enum impl(alias T) = false;
6450 enum isInstanceOf = impl!T;
6451 }
6452
6453 ///
6454 @safe unittest
6455 {
6456 static struct Foo(T...) { }
6457 static struct Bar(T...) { }
6458 static struct Doo(T) { }
6459 static struct ABC(int x) { }
6460 static void fun(T)() { }
6461 template templ(T) { }
6462
6463 static assert(isInstanceOf!(Foo, Foo!int));
6464 static assert(!isInstanceOf!(Foo, Bar!int));
6465 static assert(!isInstanceOf!(Foo, int));
6466 static assert(isInstanceOf!(Doo, Doo!int));
6467 static assert(isInstanceOf!(ABC, ABC!1));
6468 static assert(!isInstanceOf!(Foo, Foo));
6469 static assert(isInstanceOf!(fun, fun!int));
6470 static assert(isInstanceOf!(templ, templ!int));
6471 }
6472
6473 @safe unittest
6474 {
6475 static void fun1(T)() { }
6476 static void fun2(T)() { }
6477 template templ1(T) { }
6478 template templ2(T) { }
6479
6480 static assert(!isInstanceOf!(fun1, fun2!int));
6481 static assert(!isInstanceOf!(templ1, templ2!int));
6482 }
6483
6484 /**
6485 * Check whether the tuple T is an expression tuple.
6486 * An expression tuple only contains expressions.
6487 *
6488 * See_Also: $(LREF isTypeTuple).
6489 */
6490 template isExpressions(T ...)
6491 {
6492 static if (T.length >= 2)
6493 enum bool isExpressions =
6494 isExpressions!(T[0 .. $/2]) &&
6495 isExpressions!(T[$/2 .. $]);
6496 else static if (T.length == 1)
6497 enum bool isExpressions =
6498 !is(T[0]) && __traits(compiles, { auto ex = T[0]; });
6499 else
6500 enum bool isExpressions = true; // default
6501 }
6502
6503 ///
6504 @safe unittest
6505 {
6506 static assert(isExpressions!(1, 2.0, "a"));
6507 static assert(!isExpressions!(int, double, string));
6508 static assert(!isExpressions!(int, 2.0, "a"));
6509 }
6510
6511 /**
6512 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
6513 */
6514
6515 alias isExpressionTuple = isExpressions;
6516
6517 @safe unittest
6518 {
6519 void foo();
6520 static int bar() { return 42; }
6521 immutable aa = [ 1: -1 ];
6522 alias myint = int;
6523
6524 static assert( isExpressionTuple!(42));
6525 static assert( isExpressionTuple!aa);
6526 static assert( isExpressionTuple!("cattywampus", 2.7, aa));
6527 static assert( isExpressionTuple!(bar()));
6528
6529 static assert(!isExpressionTuple!isExpressionTuple);
6530 static assert(!isExpressionTuple!foo);
6531 static assert(!isExpressionTuple!( (a) { } ));
6532 static assert(!isExpressionTuple!int);
6533 static assert(!isExpressionTuple!myint);
6534 }
6535
6536
6537 /**
6538 * Check whether the tuple $(D T) is a type tuple.
6539 * A type tuple only contains types.
6540 *
6541 * See_Also: $(LREF isExpressions).
6542 */
6543 template isTypeTuple(T...)
6544 {
6545 static if (T.length >= 2)
6546 enum bool isTypeTuple = isTypeTuple!(T[0 .. $/2]) && isTypeTuple!(T[$/2 .. $]);
6547 else static if (T.length == 1)
6548 enum bool isTypeTuple = is(T[0]);
6549 else
6550 enum bool isTypeTuple = true; // default
6551 }
6552
6553 ///
6554 @safe unittest
6555 {
6556 static assert(isTypeTuple!(int, float, string));
6557 static assert(!isTypeTuple!(1, 2.0, "a"));
6558 static assert(!isTypeTuple!(1, double, string));
6559 }
6560
6561 @safe unittest
6562 {
6563 class C {}
6564 void func(int) {}
6565 auto c = new C;
6566 enum CONST = 42;
6567
6568 static assert( isTypeTuple!int);
6569 static assert( isTypeTuple!string);
6570 static assert( isTypeTuple!C);
6571 static assert( isTypeTuple!(typeof(func)));
6572 static assert( isTypeTuple!(int, char, double));
6573
6574 static assert(!isTypeTuple!c);
6575 static assert(!isTypeTuple!isTypeTuple);
6576 static assert(!isTypeTuple!CONST);
6577 }
6578
6579
6580 /**
6581 Detect whether symbol or type $(D T) is a function pointer.
6582 */
6583 template isFunctionPointer(T...)
6584 if (T.length == 1)
6585 {
6586 static if (is(T[0] U) || is(typeof(T[0]) U))
6587 {
6588 static if (is(U F : F*) && is(F == function))
6589 enum bool isFunctionPointer = true;
6590 else
6591 enum bool isFunctionPointer = false;
6592 }
6593 else
6594 enum bool isFunctionPointer = false;
6595 }
6596
6597 ///
6598 @safe unittest
6599 {
6600 static void foo() {}
6601 void bar() {}
6602
6603 auto fpfoo = &foo;
6604 static assert( isFunctionPointer!fpfoo);
6605 static assert( isFunctionPointer!(void function()));
6606
6607 auto dgbar = &bar;
6608 static assert(!isFunctionPointer!dgbar);
6609 static assert(!isFunctionPointer!(void delegate()));
6610 static assert(!isFunctionPointer!foo);
6611 static assert(!isFunctionPointer!bar);
6612
6613 static assert( isFunctionPointer!((int a) {}));
6614 }
6615
6616 /**
6617 Detect whether symbol or type $(D T) is a delegate.
6618 */
6619 template isDelegate(T...)
6620 if (T.length == 1)
6621 {
6622 static if (is(typeof(& T[0]) U : U*) && is(typeof(& T[0]) U == delegate))
6623 {
6624 // T is a (nested) function symbol.
6625 enum bool isDelegate = true;
6626 }
6627 else static if (is(T[0] W) || is(typeof(T[0]) W))
6628 {
6629 // T is an expression or a type. Take the type of it and examine.
6630 enum bool isDelegate = is(W == delegate);
6631 }
6632 else
6633 enum bool isDelegate = false;
6634 }
6635
6636 ///
6637 @safe unittest
6638 {
6639 static void sfunc() { }
6640 int x;
6641 void func() { x++; }
6642
6643 int delegate() dg;
6644 assert(isDelegate!dg);
6645 assert(isDelegate!(int delegate()));
6646 assert(isDelegate!(typeof(&func)));
6647
6648 int function() fp;
6649 assert(!isDelegate!fp);
6650 assert(!isDelegate!(int function()));
6651 assert(!isDelegate!(typeof(&sfunc)));
6652 }
6653
6654 /**
6655 Detect whether symbol or type $(D T) is a function, a function pointer or a delegate.
6656 */
6657 template isSomeFunction(T...)
6658 if (T.length == 1)
6659 {
6660 static if (is(typeof(& T[0]) U : U*) && is(U == function) || is(typeof(& T[0]) U == delegate))
6661 {
6662 // T is a (nested) function symbol.
6663 enum bool isSomeFunction = true;
6664 }
6665 else static if (is(T[0] W) || is(typeof(T[0]) W))
6666 {
6667 // T is an expression or a type. Take the type of it and examine.
6668 static if (is(W F : F*) && is(F == function))
6669 enum bool isSomeFunction = true; // function pointer
6670 else
6671 enum bool isSomeFunction = is(W == function) || is(W == delegate);
6672 }
6673 else
6674 enum bool isSomeFunction = false;
6675 }
6676
6677 @safe unittest
6678 {
6679 static real func(ref int) { return 0; }
6680 static void prop() @property { }
6681 void nestedFunc() { }
6682 void nestedProp() @property { }
6683 class C
6684 {
6685 real method(ref int) { return 0; }
6686 real prop() @property { return 0; }
6687 }
6688 auto c = new C;
6689 auto fp = &func;
6690 auto dg = &c.method;
6691 real val;
6692
6693 static assert( isSomeFunction!func);
6694 static assert( isSomeFunction!prop);
6695 static assert( isSomeFunction!nestedFunc);
6696 static assert( isSomeFunction!nestedProp);
6697 static assert( isSomeFunction!(C.method));
6698 static assert( isSomeFunction!(C.prop));
6699 static assert( isSomeFunction!(c.prop));
6700 static assert( isSomeFunction!(c.prop));
6701 static assert( isSomeFunction!fp);
6702 static assert( isSomeFunction!dg);
6703 static assert( isSomeFunction!(typeof(func)));
6704 static assert( isSomeFunction!(real function(ref int)));
6705 static assert( isSomeFunction!(real delegate(ref int)));
6706 static assert( isSomeFunction!((int a) { return a; }));
6707
6708 static assert(!isSomeFunction!int);
6709 static assert(!isSomeFunction!val);
6710 static assert(!isSomeFunction!isSomeFunction);
6711 }
6712
6713
6714 /**
6715 Detect whether $(D T) is a callable object, which can be called with the
6716 function call operator $(D $(LPAREN)...$(RPAREN)).
6717 */
6718 template isCallable(T...)
6719 if (T.length == 1)
6720 {
6721 static if (is(typeof(& T[0].opCall) == delegate))
6722 // T is a object which has a member function opCall().
6723 enum bool isCallable = true;
6724 else static if (is(typeof(& T[0].opCall) V : V*) && is(V == function))
6725 // T is a type which has a static member function opCall().
6726 enum bool isCallable = true;
6727 else
6728 enum bool isCallable = isSomeFunction!T;
6729 }
6730
6731 ///
6732 @safe unittest
6733 {
6734 interface I { real value() @property; }
6735 struct S { static int opCall(int) { return 0; } }
6736 class C { int opCall(int) { return 0; } }
6737 auto c = new C;
6738
6739 static assert( isCallable!c);
6740 static assert( isCallable!S);
6741 static assert( isCallable!(c.opCall));
6742 static assert( isCallable!(I.value));
6743 static assert( isCallable!((int a) { return a; }));
6744
6745 static assert(!isCallable!I);
6746 }
6747
6748
6749 /**
6750 * Detect whether $(D T) is an abstract function.
6751 */
6752 template isAbstractFunction(T...)
6753 if (T.length == 1)
6754 {
6755 enum bool isAbstractFunction = __traits(isAbstractFunction, T[0]);
6756 }
6757
6758 @safe unittest
6759 {
6760 struct S { void foo() { } }
6761 class C { void foo() { } }
6762 class AC { abstract void foo(); }
6763 static assert(!isAbstractFunction!(int));
6764 static assert(!isAbstractFunction!(S.foo));
6765 static assert(!isAbstractFunction!(C.foo));
6766 static assert( isAbstractFunction!(AC.foo));
6767 }
6768
6769 /**
6770 * Detect whether $(D T) is a final function.
6771 */
6772 template isFinalFunction(T...)
6773 if (T.length == 1)
6774 {
6775 enum bool isFinalFunction = __traits(isFinalFunction, T[0]);
6776 }
6777
6778 ///
6779 @safe unittest
6780 {
6781 struct S { void bar() { } }
6782 final class FC { void foo(); }
6783 class C
6784 {
6785 void bar() { }
6786 final void foo();
6787 }
6788 static assert(!isFinalFunction!(int));
6789 static assert(!isFinalFunction!(S.bar));
6790 static assert( isFinalFunction!(FC.foo));
6791 static assert(!isFinalFunction!(C.bar));
6792 static assert( isFinalFunction!(C.foo));
6793 }
6794
6795 /**
6796 Determines whether function $(D f) requires a context pointer.
6797 */
6798 template isNestedFunction(alias f)
6799 {
6800 enum isNestedFunction = __traits(isNested, f);
6801 }
6802
6803 @safe unittest
6804 {
6805 static void f() { }
6806 void g() { }
6807 static assert(!isNestedFunction!f);
6808 static assert( isNestedFunction!g);
6809 }
6810
6811 /**
6812 * Detect whether $(D T) is an abstract class.
6813 */
6814 template isAbstractClass(T...)
6815 if (T.length == 1)
6816 {
6817 enum bool isAbstractClass = __traits(isAbstractClass, T[0]);
6818 }
6819
6820 ///
6821 @safe unittest
6822 {
6823 struct S { }
6824 class C { }
6825 abstract class AC { }
6826 static assert(!isAbstractClass!S);
6827 static assert(!isAbstractClass!C);
6828 static assert( isAbstractClass!AC);
6829 C c;
6830 static assert(!isAbstractClass!c);
6831 AC ac;
6832 static assert( isAbstractClass!ac);
6833 }
6834
6835 /**
6836 * Detect whether $(D T) is a final class.
6837 */
6838 template isFinalClass(T...)
6839 if (T.length == 1)
6840 {
6841 enum bool isFinalClass = __traits(isFinalClass, T[0]);
6842 }
6843
6844 ///
6845 @safe unittest
6846 {
6847 class C { }
6848 abstract class AC { }
6849 final class FC1 : C { }
6850 final class FC2 { }
6851 static assert(!isFinalClass!C);
6852 static assert(!isFinalClass!AC);
6853 static assert( isFinalClass!FC1);
6854 static assert( isFinalClass!FC2);
6855 C c;
6856 static assert(!isFinalClass!c);
6857 FC1 fc1;
6858 static assert( isFinalClass!fc1);
6859 }
6860
6861 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6862 // General Types
6863 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6864
6865 /**
6866 Removes all qualifiers, if any, from type $(D T).
6867 */
6868 template Unqual(T)
6869 {
6870 version (none) // Error: recursive alias declaration @@@BUG1308@@@
6871 {
6872 static if (is(T U == const U)) alias Unqual = Unqual!U;
6873 else static if (is(T U == immutable U)) alias Unqual = Unqual!U;
6874 else static if (is(T U == inout U)) alias Unqual = Unqual!U;
6875 else static if (is(T U == shared U)) alias Unqual = Unqual!U;
6876 else alias Unqual = T;
6877 }
6878 else // workaround
6879 {
6880 static if (is(T U == immutable U)) alias Unqual = U;
6881 else static if (is(T U == shared inout const U)) alias Unqual = U;
6882 else static if (is(T U == shared inout U)) alias Unqual = U;
6883 else static if (is(T U == shared const U)) alias Unqual = U;
6884 else static if (is(T U == shared U)) alias Unqual = U;
6885 else static if (is(T U == inout const U)) alias Unqual = U;
6886 else static if (is(T U == inout U)) alias Unqual = U;
6887 else static if (is(T U == const U)) alias Unqual = U;
6888 else alias Unqual = T;
6889 }
6890 }
6891
6892 ///
6893 @safe unittest
6894 {
6895 static assert(is(Unqual!int == int));
6896 static assert(is(Unqual!(const int) == int));
6897 static assert(is(Unqual!(immutable int) == int));
6898 static assert(is(Unqual!(shared int) == int));
6899 static assert(is(Unqual!(shared(const int)) == int));
6900 }
6901
6902 @safe unittest
6903 {
6904 static assert(is(Unqual!( int) == int));
6905 static assert(is(Unqual!( const int) == int));
6906 static assert(is(Unqual!( inout int) == int));
6907 static assert(is(Unqual!( inout const int) == int));
6908 static assert(is(Unqual!(shared int) == int));
6909 static assert(is(Unqual!(shared const int) == int));
6910 static assert(is(Unqual!(shared inout int) == int));
6911 static assert(is(Unqual!(shared inout const int) == int));
6912 static assert(is(Unqual!( immutable int) == int));
6913
6914 alias ImmIntArr = immutable(int[]);
6915 static assert(is(Unqual!ImmIntArr == immutable(int)[]));
6916 }
6917
6918 // [For internal use]
6919 package template ModifyTypePreservingTQ(alias Modifier, T)
6920 {
6921 static if (is(T U == immutable U)) alias ModifyTypePreservingTQ = immutable Modifier!U;
6922 else static if (is(T U == shared inout const U)) alias ModifyTypePreservingTQ = shared inout const Modifier!U;
6923 else static if (is(T U == shared inout U)) alias ModifyTypePreservingTQ = shared inout Modifier!U;
6924 else static if (is(T U == shared const U)) alias ModifyTypePreservingTQ = shared const Modifier!U;
6925 else static if (is(T U == shared U)) alias ModifyTypePreservingTQ = shared Modifier!U;
6926 else static if (is(T U == inout const U)) alias ModifyTypePreservingTQ = inout const Modifier!U;
6927 else static if (is(T U == inout U)) alias ModifyTypePreservingTQ = inout Modifier!U;
6928 else static if (is(T U == const U)) alias ModifyTypePreservingTQ = const Modifier!U;
6929 else alias ModifyTypePreservingTQ = Modifier!T;
6930 }
6931
6932 @safe unittest
6933 {
6934 alias Intify(T) = int;
6935 static assert(is(ModifyTypePreservingTQ!(Intify, real) == int));
6936 static assert(is(ModifyTypePreservingTQ!(Intify, const real) == const int));
6937 static assert(is(ModifyTypePreservingTQ!(Intify, inout real) == inout int));
6938 static assert(is(ModifyTypePreservingTQ!(Intify, inout const real) == inout const int));
6939 static assert(is(ModifyTypePreservingTQ!(Intify, shared real) == shared int));
6940 static assert(is(ModifyTypePreservingTQ!(Intify, shared const real) == shared const int));
6941 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout real) == shared inout int));
6942 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout const real) == shared inout const int));
6943 static assert(is(ModifyTypePreservingTQ!(Intify, immutable real) == immutable int));
6944 }
6945
6946 /**
6947 * Copies type qualifiers from $(D FromType) to $(D ToType).
6948 *
6949 * Supported type qualifiers:
6950 * $(UL
6951 * $(LI $(D const))
6952 * $(LI $(D inout))
6953 * $(LI $(D immutable))
6954 * $(LI $(D shared))
6955 * )
6956 */
6957 template CopyTypeQualifiers(FromType, ToType)
6958 {
6959 alias T(U) = ToType;
6960 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
6961 }
6962
6963 ///
6964 @safe unittest
6965 {
6966 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
6967 }
6968
6969 @safe unittest
6970 {
6971 static assert(is(CopyTypeQualifiers!( real, int) == int));
6972 static assert(is(CopyTypeQualifiers!( const real, int) == const int));
6973 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int));
6974 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int));
6975 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int));
6976 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int));
6977 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int));
6978 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
6979 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int));
6980 }
6981
6982 /**
6983 Returns the type of `Target` with the "constness" of `Source`. A type's $(B constness)
6984 refers to whether it is `const`, `immutable`, or `inout`. If `source` has no constness, the
6985 returned type will be the same as `Target`.
6986 */
6987 template CopyConstness(FromType, ToType)
6988 {
6989 alias Unshared(T) = T;
6990 alias Unshared(T: shared U, U) = U;
6991
6992 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
6993 }
6994
6995 ///
6996 @safe unittest
6997 {
6998 const(int) i;
6999 CopyConstness!(typeof(i), float) f;
7000 assert( is(typeof(f) == const float));
7001
7002 CopyConstness!(char, uint) u;
7003 assert( is(typeof(u) == uint));
7004
7005 //The 'shared' qualifier will not be copied
7006 assert(!is(CopyConstness!(shared bool, int) == shared int));
7007
7008 //But the constness will be
7009 assert( is(CopyConstness!(shared const real, double) == const double));
7010
7011 //Careful, const(int)[] is a mutable array of const(int)
7012 alias MutT = CopyConstness!(const(int)[], int);
7013 assert(!is(MutT == const(int)));
7014
7015 //Okay, const(int[]) applies to array and contained ints
7016 alias CstT = CopyConstness!(const(int[]), int);
7017 assert( is(CstT == const(int)));
7018 }
7019
7020 @safe unittest
7021 {
7022 struct Test
7023 {
7024 void method1() {}
7025 void method2() const {}
7026 void method3() immutable {}
7027 }
7028
7029 assert(is(CopyConstness!(typeof(Test.method1), real) == real));
7030
7031 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
7032
7033 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
7034 }
7035
7036 @safe unittest
7037 {
7038 assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
7039 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
7040 }
7041
7042 @safe unittest
7043 {
7044 static assert(is(CopyConstness!( int, real) == real));
7045 static assert(is(CopyConstness!(const int, real) == const real));
7046 static assert(is(CopyConstness!(inout int, real) == inout real));
7047 static assert(is(CopyConstness!(inout const int, real) == inout const real));
7048 static assert(is(CopyConstness!(shared int, real) == real));
7049 static assert(is(CopyConstness!(shared const int, real) == const real));
7050 static assert(is(CopyConstness!(shared inout int, real) == inout real));
7051 static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
7052 static assert(is(CopyConstness!(immutable int, real) == immutable real));
7053 }
7054
7055 /**
7056 Returns the inferred type of the loop variable when a variable of type T
7057 is iterated over using a $(D foreach) loop with a single loop variable and
7058 automatically inferred return type. Note that this may not be the same as
7059 $(D std.range.ElementType!Range) in the case of narrow strings, or if T
7060 has both opApply and a range interface.
7061 */
7062 template ForeachType(T)
7063 {
7064 alias ForeachType = ReturnType!(typeof(
7065 (inout int x = 0)
7066 {
7067 foreach (elem; T.init)
7068 {
7069 return elem;
7070 }
7071 assert(0);
7072 }));
7073 }
7074
7075 ///
7076 @safe unittest
7077 {
7078 static assert(is(ForeachType!(uint[]) == uint));
7079 static assert(is(ForeachType!string == immutable(char)));
7080 static assert(is(ForeachType!(string[string]) == string));
7081 static assert(is(ForeachType!(inout(int)[]) == inout(int)));
7082 }
7083
7084
7085 /**
7086 * Strips off all $(D enum)s from type $(D T).
7087 */
7088 template OriginalType(T)
7089 {
7090 template Impl(T)
7091 {
7092 static if (is(T U == enum)) alias Impl = OriginalType!U;
7093 else alias Impl = T;
7094 }
7095
7096 alias OriginalType = ModifyTypePreservingTQ!(Impl, T);
7097 }
7098
7099 ///
7100 @safe unittest
7101 {
7102 enum E : real { a }
7103 enum F : E { a = E.a }
7104 alias G = const(F);
7105 static assert(is(OriginalType!E == real));
7106 static assert(is(OriginalType!F == real));
7107 static assert(is(OriginalType!G == const real));
7108 }
7109
7110 /**
7111 * Get the Key type of an Associative Array.
7112 */
7113 alias KeyType(V : V[K], K) = K;
7114
7115 ///
7116 @safe unittest
7117 {
7118 import std.traits;
7119 alias Hash = int[string];
7120 static assert(is(KeyType!Hash == string));
7121 static assert(is(ValueType!Hash == int));
7122 KeyType!Hash str = "a"; // str is declared as string
7123 ValueType!Hash num = 1; // num is declared as int
7124 }
7125
7126 /**
7127 * Get the Value type of an Associative Array.
7128 */
7129 alias ValueType(V : V[K], K) = V;
7130
7131 ///
7132 @safe unittest
7133 {
7134 import std.traits;
7135 alias Hash = int[string];
7136 static assert(is(KeyType!Hash == string));
7137 static assert(is(ValueType!Hash == int));
7138 KeyType!Hash str = "a"; // str is declared as string
7139 ValueType!Hash num = 1; // num is declared as int
7140 }
7141
7142 /**
7143 * Returns the corresponding unsigned type for T. T must be a numeric
7144 * integral type, otherwise a compile-time error occurs.
7145 */
7146 template Unsigned(T)
7147 {
7148 template Impl(T)
7149 {
7150 static if (is(T : __vector(V[N]), V, size_t N))
7151 alias Impl = __vector(Impl!V[N]);
7152 else static if (isUnsigned!T)
7153 alias Impl = T;
7154 else static if (isSigned!T && !isFloatingPoint!T)
7155 {
7156 static if (is(T == byte )) alias Impl = ubyte;
7157 static if (is(T == short)) alias Impl = ushort;
7158 static if (is(T == int )) alias Impl = uint;
7159 static if (is(T == long )) alias Impl = ulong;
7160 static if (is(ucent) && is(T == cent )) alias Impl = ucent;
7161 }
7162 else
7163 static assert(false, "Type " ~ T.stringof ~
7164 " does not have an Unsigned counterpart");
7165 }
7166
7167 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
7168 }
7169
7170 @safe unittest
7171 {
7172 alias U1 = Unsigned!int;
7173 alias U2 = Unsigned!(const(int));
7174 alias U3 = Unsigned!(immutable(int));
7175 static assert(is(U1 == uint));
7176 static assert(is(U2 == const(uint)));
7177 static assert(is(U3 == immutable(uint)));
7178 static if (is(__vector(int[4])) && is(__vector(uint[4])))
7179 {
7180 alias UV1 = Unsigned!(__vector(int[4]));
7181 alias UV2 = Unsigned!(const(__vector(int[4])));
7182 static assert(is(UV1 == __vector(uint[4])));
7183 static assert(is(UV2 == const(__vector(uint[4]))));
7184 }
7185 //struct S {}
7186 //alias U2 = Unsigned!S;
7187 //alias U3 = Unsigned!double;
7188 static if (is(ucent))
7189 {
7190 alias U4 = Unsigned!cent;
7191 alias U5 = Unsigned!(const(cent));
7192 alias U6 = Unsigned!(immutable(cent));
7193 static assert(is(U4 == ucent));
7194 static assert(is(U5 == const(ucent)));
7195 static assert(is(U6 == immutable(ucent)));
7196 }
7197 }
7198
7199 /**
7200 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
7201 than one type is of the same size, the leftmost argument of these in will be
7202 returned.
7203 */
7204 template Largest(T...) if (T.length >= 1)
7205 {
7206 static if (T.length == 1)
7207 {
7208 alias Largest = T[0];
7209 }
7210 else static if (T.length == 2)
7211 {
7212 static if (T[0].sizeof >= T[1].sizeof)
7213 {
7214 alias Largest = T[0];
7215 }
7216 else
7217 {
7218 alias Largest = T[1];
7219 }
7220 }
7221 else
7222 {
7223 alias Largest = Largest!(Largest!(T[0 .. $/2]), Largest!(T[$/2 .. $]));
7224 }
7225 }
7226
7227 ///
7228 @safe unittest
7229 {
7230 static assert(is(Largest!(uint, ubyte, ushort, real) == real));
7231 static assert(is(Largest!(ulong, double) == ulong));
7232 static assert(is(Largest!(double, ulong) == double));
7233 static assert(is(Largest!(uint, byte, double, short) == double));
7234 static if (is(ucent))
7235 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
7236 }
7237
7238 /**
7239 Returns the corresponding signed type for T. T must be a numeric integral type,
7240 otherwise a compile-time error occurs.
7241 */
7242 template Signed(T)
7243 {
7244 template Impl(T)
7245 {
7246 static if (is(T : __vector(V[N]), V, size_t N))
7247 alias Impl = __vector(Impl!V[N]);
7248 else static if (isSigned!T)
7249 alias Impl = T;
7250 else static if (isUnsigned!T)
7251 {
7252 static if (is(T == ubyte )) alias Impl = byte;
7253 static if (is(T == ushort)) alias Impl = short;
7254 static if (is(T == uint )) alias Impl = int;
7255 static if (is(T == ulong )) alias Impl = long;
7256 static if (is(ucent) && is(T == ucent )) alias Impl = cent;
7257 }
7258 else
7259 static assert(false, "Type " ~ T.stringof ~
7260 " does not have an Signed counterpart");
7261 }
7262
7263 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
7264 }
7265
7266 ///
7267 @safe unittest
7268 {
7269 alias S1 = Signed!uint;
7270 static assert(is(S1 == int));
7271 alias S2 = Signed!(const(uint));
7272 static assert(is(S2 == const(int)));
7273 alias S3 = Signed!(immutable(uint));
7274 static assert(is(S3 == immutable(int)));
7275 static if (is(ucent))
7276 {
7277 alias S4 = Signed!ucent;
7278 static assert(is(S4 == cent));
7279 }
7280 }
7281
7282 @safe unittest
7283 {
7284 static assert(is(Signed!float == float));
7285 static if (is(__vector(int[4])) && is(__vector(uint[4])))
7286 {
7287 alias SV1 = Signed!(__vector(uint[4]));
7288 alias SV2 = Signed!(const(__vector(uint[4])));
7289 static assert(is(SV1 == __vector(int[4])));
7290 static assert(is(SV2 == const(__vector(int[4]))));
7291 }
7292 }
7293
7294
7295 /**
7296 Returns the most negative value of the numeric type T.
7297 */
7298 template mostNegative(T)
7299 if (isNumeric!T || isSomeChar!T || isBoolean!T)
7300 {
7301 static if (is(typeof(T.min_normal)))
7302 enum mostNegative = -T.max;
7303 else static if (T.min == 0)
7304 enum byte mostNegative = 0;
7305 else
7306 enum mostNegative = T.min;
7307 }
7308
7309 ///
7310 @safe unittest
7311 {
7312 static assert(mostNegative!float == -float.max);
7313 static assert(mostNegative!double == -double.max);
7314 static assert(mostNegative!real == -real.max);
7315 static assert(mostNegative!bool == false);
7316 }
7317
7318 ///
7319 @safe unittest
7320 {
7321 foreach (T; AliasSeq!(bool, byte, short, int, long))
7322 static assert(mostNegative!T == T.min);
7323
7324 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
7325 static assert(mostNegative!T == 0);
7326 }
7327
7328 /**
7329 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
7330 to in multi-term arithmetic expressions.
7331 */
7332 template Promoted(T)
7333 if (isScalarType!T)
7334 {
7335 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
7336 }
7337
7338 ///
7339 @safe unittest
7340 {
7341 ubyte a = 3, b = 5;
7342 static assert(is(typeof(a * b) == Promoted!ubyte));
7343 static assert(is(Promoted!ubyte == int));
7344
7345 static assert(is(Promoted!(shared(bool)) == shared(int)));
7346 static assert(is(Promoted!(const(int)) == const(int)));
7347 static assert(is(Promoted!double == double));
7348 }
7349
7350 @safe unittest
7351 {
7352 // promote to int:
7353 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
7354 {
7355 static assert(is(Promoted!T == int));
7356 static assert(is(Promoted!(shared(const T)) == shared(const int)));
7357 }
7358
7359 // already promoted:
7360 foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
7361 {
7362 static assert(is(Promoted!T == T));
7363 static assert(is(Promoted!(immutable(T)) == immutable(T)));
7364 }
7365 }
7366
7367 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7368 // Misc.
7369 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7370
7371 /**
7372 Returns the mangled name of symbol or type $(D sth).
7373
7374 $(D mangledName) is the same as builtin $(D .mangleof) property, but
7375 might be more convenient in generic code, e.g. as a template argument
7376 when invoking staticMap.
7377 */
7378 template mangledName(sth...)
7379 if (sth.length == 1)
7380 {
7381 enum string mangledName = sth[0].mangleof;
7382 }
7383
7384 ///
7385 @safe unittest
7386 {
7387 alias TL = staticMap!(mangledName, int, const int, immutable int);
7388 static assert(TL == AliasSeq!("i", "xi", "yi"));
7389 }
7390
7391 version (unittest) void freeFunc(string);
7392
7393 @safe unittest
7394 {
7395 class C { int value() @property { return 0; } }
7396 static assert(mangledName!int == int.mangleof);
7397 static assert(mangledName!C == C.mangleof);
7398 static assert(mangledName!(C.value) == C.value.mangleof);
7399 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
7400 static assert(mangledName!mangledName == "3std6traits11mangledName");
7401 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
7402 int x;
7403 static if (is(typeof({ return x; }) : int delegate() pure)) // issue 9148
7404 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
7405 else
7406 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
7407 }
7408
7409 @system unittest
7410 {
7411 // @system due to demangle
7412 // Test for bug 5718
7413 import std.demangle : demangle;
7414 int foo;
7415 auto foo_demangled = demangle(mangledName!foo);
7416 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
7417 foo_demangled);
7418
7419 void bar();
7420 auto bar_demangled = demangle(mangledName!bar);
7421 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
7422 }
7423
7424
7425
7426 // XXX Select & select should go to another module. (functional or algorithm?)
7427
7428 /**
7429 Aliases itself to $(D T[0]) if the boolean $(D condition) is $(D true)
7430 and to $(D T[1]) otherwise.
7431 */
7432 template Select(bool condition, T...) if (T.length == 2)
7433 {
7434 import std.meta : Alias;
7435 alias Select = Alias!(T[!condition]);
7436 }
7437
7438 ///
7439 @safe unittest
7440 {
7441 // can select types
7442 static assert(is(Select!(true, int, long) == int));
7443 static assert(is(Select!(false, int, long) == long));
7444 static struct Foo {}
7445 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
7446
7447 // can select symbols
7448 int a = 1;
7449 int b = 2;
7450 alias selA = Select!(true, a, b);
7451 alias selB = Select!(false, a, b);
7452 assert(selA == 1);
7453 assert(selB == 2);
7454
7455 // can select (compile-time) expressions
7456 enum val = Select!(false, -4, 9 - 6);
7457 static assert(val == 3);
7458 }
7459
7460 /**
7461 If $(D cond) is $(D true), returns $(D a) without evaluating $(D
7462 b). Otherwise, returns $(D b) without evaluating $(D a).
7463 */
7464 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
7465 /// Ditto
7466 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
7467
7468 @safe unittest
7469 {
7470 real pleasecallme() { return 0; }
7471 int dontcallme() { assert(0); }
7472 auto a = select!true(pleasecallme(), dontcallme());
7473 auto b = select!false(dontcallme(), pleasecallme());
7474 static assert(is(typeof(a) == real));
7475 static assert(is(typeof(b) == real));
7476 }
7477
7478 /++
7479 Determine if a symbol has a given
7480 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
7481
7482 See_Also:
7483 $(LREF getUDAs)
7484 +/
7485 template hasUDA(alias symbol, alias attribute)
7486 {
7487 enum hasUDA = getUDAs!(symbol, attribute).length != 0;
7488 }
7489
7490 ///
7491 @safe unittest
7492 {
7493 enum E;
7494 struct S {}
7495
7496 @("alpha") int a;
7497 static assert(hasUDA!(a, "alpha"));
7498 static assert(!hasUDA!(a, S));
7499 static assert(!hasUDA!(a, E));
7500
7501 @(E) int b;
7502 static assert(!hasUDA!(b, "alpha"));
7503 static assert(!hasUDA!(b, S));
7504 static assert(hasUDA!(b, E));
7505
7506 @E int c;
7507 static assert(!hasUDA!(c, "alpha"));
7508 static assert(!hasUDA!(c, S));
7509 static assert(hasUDA!(c, E));
7510
7511 @(S, E) int d;
7512 static assert(!hasUDA!(d, "alpha"));
7513 static assert(hasUDA!(d, S));
7514 static assert(hasUDA!(d, E));
7515
7516 @S int e;
7517 static assert(!hasUDA!(e, "alpha"));
7518 static assert(hasUDA!(e, S));
7519 static assert(!hasUDA!(e, S()));
7520 static assert(!hasUDA!(e, E));
7521
7522 @S() int f;
7523 static assert(!hasUDA!(f, "alpha"));
7524 static assert(hasUDA!(f, S));
7525 static assert(hasUDA!(f, S()));
7526 static assert(!hasUDA!(f, E));
7527
7528 @(S, E, "alpha") int g;
7529 static assert(hasUDA!(g, "alpha"));
7530 static assert(hasUDA!(g, S));
7531 static assert(hasUDA!(g, E));
7532
7533 @(100) int h;
7534 static assert(hasUDA!(h, 100));
7535
7536 struct Named { string name; }
7537
7538 @Named("abc") int i;
7539 static assert(hasUDA!(i, Named));
7540 static assert(hasUDA!(i, Named("abc")));
7541 static assert(!hasUDA!(i, Named("def")));
7542
7543 struct AttrT(T)
7544 {
7545 string name;
7546 T value;
7547 }
7548
7549 @AttrT!int("answer", 42) int j;
7550 static assert(hasUDA!(j, AttrT));
7551 static assert(hasUDA!(j, AttrT!int));
7552 static assert(!hasUDA!(j, AttrT!string));
7553
7554 @AttrT!string("hello", "world") int k;
7555 static assert(hasUDA!(k, AttrT));
7556 static assert(!hasUDA!(k, AttrT!int));
7557 static assert(hasUDA!(k, AttrT!string));
7558
7559 struct FuncAttr(alias f) { alias func = f; }
7560 static int fourtyTwo() { return 42; }
7561 static size_t getLen(string s) { return s.length; }
7562
7563 @FuncAttr!getLen int l;
7564 static assert(hasUDA!(l, FuncAttr));
7565 static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
7566 static assert(hasUDA!(l, FuncAttr!getLen));
7567 static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
7568 static assert(!hasUDA!(l, FuncAttr!getLen()));
7569
7570 @FuncAttr!getLen() int m;
7571 static assert(hasUDA!(m, FuncAttr));
7572 static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
7573 static assert(hasUDA!(m, FuncAttr!getLen));
7574 static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
7575 static assert(hasUDA!(m, FuncAttr!getLen()));
7576 }
7577
7578 /++
7579 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
7580 from the given symbol.
7581
7582 If the UDA is a type, then any UDAs of the same type on the symbol will
7583 match. If the UDA is a template for a type, then any UDA which is an
7584 instantiation of that template will match. And if the UDA is a value,
7585 then any UDAs on the symbol which are equal to that value will match.
7586
7587 See_Also:
7588 $(LREF hasUDA)
7589 +/
7590 template getUDAs(alias symbol, alias attribute)
7591 {
7592 import std.meta : Filter;
7593
7594 template isDesiredUDA(alias toCheck)
7595 {
7596 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
7597 {
7598 static if (__traits(compiles, toCheck == attribute))
7599 enum isDesiredUDA = toCheck == attribute;
7600 else
7601 enum isDesiredUDA = false;
7602 }
7603 else static if (is(typeof(toCheck)))
7604 {
7605 static if (__traits(isTemplate, attribute))
7606 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck));
7607 else
7608 enum isDesiredUDA = is(typeof(toCheck) == attribute);
7609 }
7610 else static if (__traits(isTemplate, attribute))
7611 enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
7612 else
7613 enum isDesiredUDA = is(toCheck == attribute);
7614 }
7615 alias getUDAs = Filter!(isDesiredUDA, __traits(getAttributes, symbol));
7616 }
7617
7618 ///
7619 @safe unittest
7620 {
7621 struct Attr
7622 {
7623 string name;
7624 int value;
7625 }
7626
7627 @Attr("Answer", 42) int a;
7628 static assert(getUDAs!(a, Attr).length == 1);
7629 static assert(getUDAs!(a, Attr)[0].name == "Answer");
7630 static assert(getUDAs!(a, Attr)[0].value == 42);
7631
7632 @(Attr("Answer", 42), "string", 9999) int b;
7633 static assert(getUDAs!(b, Attr).length == 1);
7634 static assert(getUDAs!(b, Attr)[0].name == "Answer");
7635 static assert(getUDAs!(b, Attr)[0].value == 42);
7636
7637 @Attr("Answer", 42) @Attr("Pi", 3) int c;
7638 static assert(getUDAs!(c, Attr).length == 2);
7639 static assert(getUDAs!(c, Attr)[0].name == "Answer");
7640 static assert(getUDAs!(c, Attr)[0].value == 42);
7641 static assert(getUDAs!(c, Attr)[1].name == "Pi");
7642 static assert(getUDAs!(c, Attr)[1].value == 3);
7643
7644 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
7645 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
7646 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
7647
7648 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
7649
7650 struct AttrT(T)
7651 {
7652 string name;
7653 T value;
7654 }
7655
7656 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
7657 static assert(getUDAs!(d, AttrT).length == 2);
7658 static assert(getUDAs!(d, AttrT)[0].name == "Answer");
7659 static assert(getUDAs!(d, AttrT)[0].value == 42);
7660 static assert(getUDAs!(d, AttrT)[1].name == "Pi");
7661 static assert(getUDAs!(d, AttrT)[1].value == 3);
7662
7663 static assert(getUDAs!(d, AttrT!uint).length == 1);
7664 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
7665 static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
7666
7667 static assert(getUDAs!(d, AttrT!int).length == 1);
7668 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
7669 static assert(getUDAs!(d, AttrT!int)[0].value == 3);
7670
7671 struct SimpleAttr {}
7672
7673 @SimpleAttr int e;
7674 static assert(getUDAs!(e, SimpleAttr).length == 1);
7675 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
7676
7677 @SimpleAttr() int f;
7678 static assert(getUDAs!(f, SimpleAttr).length == 1);
7679 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
7680
7681 struct FuncAttr(alias f) { alias func = f; }
7682 static int add42(int v) { return v + 42; }
7683 static string concat(string l, string r) { return l ~ r; }
7684
7685 @FuncAttr!add42 int g;
7686 static assert(getUDAs!(g, FuncAttr).length == 1);
7687 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
7688
7689 static assert(getUDAs!(g, FuncAttr!add42).length == 1);
7690 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
7691
7692 static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
7693
7694 static assert(getUDAs!(g, FuncAttr!concat).length == 0);
7695 static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
7696
7697 @FuncAttr!add42() int h;
7698 static assert(getUDAs!(h, FuncAttr).length == 1);
7699 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
7700
7701 static assert(getUDAs!(h, FuncAttr!add42).length == 1);
7702 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
7703
7704 static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
7705 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
7706
7707 static assert(getUDAs!(h, FuncAttr!concat).length == 0);
7708 static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
7709
7710 @("alpha") @(42) int i;
7711 static assert(getUDAs!(i, "alpha").length == 1);
7712 static assert(getUDAs!(i, "alpha")[0] == "alpha");
7713
7714 static assert(getUDAs!(i, 42).length == 1);
7715 static assert(getUDAs!(i, 42)[0] == 42);
7716
7717 static assert(getUDAs!(i, 'c').length == 0);
7718 }
7719
7720 /**
7721 * Gets all symbols within `symbol` that have the given user-defined attribute.
7722 * This is not recursive; it will not search for symbols within symbols such as
7723 * nested structs or unions.
7724 */
7725 template getSymbolsByUDA(alias symbol, alias attribute)
7726 {
7727 import std.format : format;
7728 import std.meta : AliasSeq, Filter;
7729
7730 // translate a list of strings into symbols. mixing in the entire alias
7731 // avoids trying to access the symbol, which could cause a privacy violation
7732 template toSymbols(names...)
7733 {
7734 static if (names.length == 0)
7735 alias toSymbols = AliasSeq!();
7736 else
7737 mixin("alias toSymbols = AliasSeq!(symbol.%s, toSymbols!(names[1..$]));"
7738 .format(names[0]));
7739 }
7740
7741 // filtering inaccessible members
7742 enum isAccessibleMember(string name) = __traits(compiles, __traits(getMember, symbol, name));
7743 alias accessibleMembers = Filter!(isAccessibleMember, __traits(allMembers, symbol));
7744
7745 // filtering not compiled members such as alias of basic types
7746 enum hasSpecificUDA(string name) = mixin("hasUDA!(symbol." ~ name ~ ", attribute)");
7747 enum isCorrectMember(string name) = __traits(compiles, hasSpecificUDA!(name));
7748
7749 alias correctMembers = Filter!(isCorrectMember, accessibleMembers);
7750 alias membersWithUDA = toSymbols!(Filter!(hasSpecificUDA, correctMembers));
7751
7752 // if the symbol itself has the UDA, tack it on to the front of the list
7753 static if (hasUDA!(symbol, attribute))
7754 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
7755 else
7756 alias getSymbolsByUDA = membersWithUDA;
7757 }
7758
7759 ///
7760 @safe unittest
7761 {
7762 enum Attr;
7763
7764 static struct A
7765 {
7766 @Attr int a;
7767 int b;
7768 @Attr void doStuff() {}
7769 void doOtherStuff() {}
7770 static struct Inner
7771 {
7772 // Not found by getSymbolsByUDA
7773 @Attr int c;
7774 }
7775 }
7776
7777 // Finds both variables and functions with the attribute, but
7778 // doesn't include the variables and functions without it.
7779 static assert(getSymbolsByUDA!(A, Attr).length == 2);
7780 // Can access attributes on the symbols returned by getSymbolsByUDA.
7781 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
7782 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
7783
7784 static struct UDA { string name; }
7785
7786 static struct B
7787 {
7788 @UDA("X")
7789 int x;
7790 @UDA("Y")
7791 int y;
7792 @(100)
7793 int z;
7794 }
7795
7796 // Finds both UDA attributes.
7797 static assert(getSymbolsByUDA!(B, UDA).length == 2);
7798 // Finds one `100` attribute.
7799 static assert(getSymbolsByUDA!(B, 100).length == 1);
7800 // Can get the value of the UDA from the return value
7801 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
7802
7803 @UDA("A")
7804 static struct C
7805 {
7806 @UDA("B")
7807 int d;
7808 }
7809
7810 // Also checks the symbol itself
7811 static assert(getSymbolsByUDA!(C, UDA).length == 2);
7812 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
7813 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
7814
7815 static struct D
7816 {
7817 int x;
7818 }
7819
7820 //Finds nothing if there is no member with specific UDA
7821 static assert(getSymbolsByUDA!(D,UDA).length == 0);
7822 }
7823
7824 // #15335: getSymbolsByUDA fails if type has private members
7825 @safe unittest
7826 {
7827 // HasPrivateMembers has, well, private members, one of which has a UDA.
7828 import std.internal.test.uda : Attr, HasPrivateMembers;
7829 // Trying access to private member from another file therefore we do not have access
7830 // for this otherwise we get deprecation warning - not visible from module
7831 static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
7832 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
7833 }
7834
7835 ///
7836 @safe unittest
7837 {
7838 enum Attr;
7839 struct A
7840 {
7841 alias int INT;
7842 alias void function(INT) SomeFunction;
7843 @Attr int a;
7844 int b;
7845 @Attr private int c;
7846 private int d;
7847 }
7848
7849 // Here everything is fine, we have access to private member c
7850 static assert(getSymbolsByUDA!(A, Attr).length == 2);
7851 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
7852 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
7853 }
7854
7855 // #16387: getSymbolsByUDA works with structs but fails with classes
7856 @safe unittest
7857 {
7858 enum Attr;
7859 class A
7860 {
7861 @Attr uint a;
7862 }
7863
7864 alias res = getSymbolsByUDA!(A, Attr);
7865 static assert(res.length == 1);
7866 static assert(res[0].stringof == "a");
7867 }
7868
7869 /**
7870 Returns: $(D true) iff all types $(D T) are the same.
7871 */
7872 template allSameType(T...)
7873 {
7874 static if (T.length <= 1)
7875 {
7876 enum bool allSameType = true;
7877 }
7878 else
7879 {
7880 enum bool allSameType = is(T[0] == T[1]) && allSameType!(T[1..$]);
7881 }
7882 }
7883
7884 ///
7885 @safe unittest
7886 {
7887 static assert(allSameType!(int, int));
7888 static assert(allSameType!(int, int, int));
7889 static assert(allSameType!(float, float, float));
7890 static assert(!allSameType!(int, double));
7891 static assert(!allSameType!(int, float, double));
7892 static assert(!allSameType!(int, float, double, real));
7893 static assert(!allSameType!(short, int, float, double, real));
7894 }
7895
7896 /**
7897 Returns: $(D true) iff the type $(D T) can be tested in an $(D
7898 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
7899 */
7900 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
7901
7902 @safe unittest
7903 {
7904 import std.meta : AliasSeq, allSatisfy;
7905 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
7906 struct BoolWrapper { bool value; }
7907 static assert(!ifTestable!(bool, a => BoolWrapper(a)));
7908 }
7909
7910 /**
7911 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
7912 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
7913 *
7914 * Returns:
7915 * `true` if `X` is a type, `false` otherwise
7916 */
7917 template isType(X...) if (X.length == 1)
7918 {
7919 enum isType = is(X[0]);
7920 }
7921
7922 ///
7923 @safe unittest
7924 {
7925 struct S {
7926 template Test() {}
7927 }
7928 class C {}
7929 interface I {}
7930 union U {}
7931 static assert(isType!int);
7932 static assert(isType!string);
7933 static assert(isType!(int[int]));
7934 static assert(isType!S);
7935 static assert(isType!C);
7936 static assert(isType!I);
7937 static assert(isType!U);
7938
7939 int n;
7940 void func(){}
7941 static assert(!isType!n);
7942 static assert(!isType!func);
7943 static assert(!isType!(S.Test));
7944 static assert(!isType!(S.Test!()));
7945 }
7946
7947 /**
7948 * Detect whether symbol or type `X` is a function. This is different that finding
7949 * if a symbol is callable or satisfying `is(X == function)`, it finds
7950 * specifically if the symbol represents a normal function declaration, i.e.
7951 * not a delegate or a function pointer.
7952 *
7953 * Returns:
7954 * `true` if `X` is a function, `false` otherwise
7955 *
7956 * See_Also:
7957 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
7958 * respectively.
7959 */
7960 template isFunction(X...) if (X.length == 1)
7961 {
7962 static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
7963 is(typeof(&X[0]) U == delegate))
7964 {
7965 // x is a (nested) function symbol.
7966 enum isFunction = true;
7967 }
7968 else static if (is(X[0] T))
7969 {
7970 // x is a type. Take the type of it and examine.
7971 enum isFunction = is(T == function);
7972 }
7973 else
7974 enum isFunction = false;
7975 }
7976
7977 ///
7978 @safe unittest
7979 {
7980 static void func(){}
7981 static assert(isFunction!func);
7982
7983 struct S
7984 {
7985 void func(){}
7986 }
7987 static assert(isFunction!(S.func));
7988 }
7989
7990 /**
7991 * Detect whether `X` is a final method or class.
7992 *
7993 * Returns:
7994 * `true` if `X` is final, `false` otherwise
7995 */
7996 template isFinal(X...) if (X.length == 1)
7997 {
7998 static if (is(X[0] == class))
7999 enum isFinal = __traits(isFinalClass, X[0]);
8000 else static if (isFunction!X)
8001 enum isFinal = __traits(isFinalFunction, X[0]);
8002 else
8003 enum isFinal = false;
8004 }
8005
8006 ///
8007 @safe unittest
8008 {
8009 class C
8010 {
8011 void nf() {}
8012 static void sf() {}
8013 final void ff() {}
8014 }
8015 final class FC { }
8016
8017 static assert(!isFinal!(C));
8018 static assert( isFinal!(FC));
8019
8020 static assert(!isFinal!(C.nf));
8021 static assert(!isFinal!(C.sf));
8022 static assert( isFinal!(C.ff));
8023 }
8024
8025 /++
8026 + Determines whether the type `S` can be copied.
8027 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
8028 + Copying for structs can be disabled by using `@disable this(this)`.
8029 +
8030 + Params:
8031 + S = The type to check.
8032 +
8033 + Returns:
8034 + `true` if `S` can be copied. `false` otherwise.
8035 + ++/
8036 enum isCopyable(S) = is(typeof(
8037 { S foo = S.init; S copy = foo; }
8038 ));
8039
8040 ///
8041 @safe unittest
8042 {
8043 struct S1 {} // Fine. Can be copied
8044 struct S2 { this(this) {}} // Fine. Can be copied
8045 struct S3 {@disable this(this) {}} // Not fine. Copying is disabled.
8046 struct S4 {S3 s;} // Not fine. A field has copying disabled.
8047
8048 class C1 {}
8049
8050 static assert( isCopyable!S1);
8051 static assert( isCopyable!S2);
8052 static assert(!isCopyable!S3);
8053 static assert(!isCopyable!S4);
8054
8055 static assert(isCopyable!C1);
8056 static assert(isCopyable!int);
8057 static assert(isCopyable!(int[]));
8058 }
8059