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