Daily bump.
[gcc.git] / libphobos / src / std / traits.d
blobf230aa3b74e43a006243d3983ab705dd0aadc139
1 // Written in the D programming language.
3 /**
4 * Templates which extract information about types and symbols at compile time.
6 * $(SCRIPT inhibitQuickIndex = 1;)
8 * $(DIVC quickindex,
9 * $(BOOKTABLE ,
10 * $(TR $(TH Category) $(TH Templates))
11 * $(TR $(TD Symbol Name traits) $(TD
12 * $(LREF fullyQualifiedName)
13 * $(LREF mangledName)
14 * $(LREF moduleName)
15 * $(LREF packageName)
16 * ))
17 * $(TR $(TD Function traits) $(TD
18 * $(LREF isFunction)
19 * $(LREF arity)
20 * $(LREF functionAttributes)
21 * $(LREF hasFunctionAttributes)
22 * $(LREF functionLinkage)
23 * $(LREF FunctionTypeOf)
24 * $(LREF isSafe)
25 * $(LREF isUnsafe)
26 * $(LREF isFinal)
27 * $(LREF ParameterDefaults)
28 * $(LREF ParameterIdentifierTuple)
29 * $(LREF ParameterStorageClassTuple)
30 * $(LREF Parameters)
31 * $(LREF ReturnType)
32 * $(LREF SetFunctionAttributes)
33 * $(LREF variadicFunctionStyle)
34 * ))
35 * $(TR $(TD Aggregate Type traits) $(TD
36 * $(LREF BaseClassesTuple)
37 * $(LREF BaseTypeTuple)
38 * $(LREF classInstanceAlignment)
39 * $(LREF EnumMembers)
40 * $(LREF FieldNameTuple)
41 * $(LREF Fields)
42 * $(LREF hasAliasing)
43 * $(LREF hasElaborateAssign)
44 * $(LREF hasElaborateCopyConstructor)
45 * $(LREF hasElaborateDestructor)
46 * $(LREF hasElaborateMove)
47 * $(LREF hasIndirections)
48 * $(LREF hasMember)
49 * $(LREF hasStaticMember)
50 * $(LREF hasNested)
51 * $(LREF hasUnsharedAliasing)
52 * $(LREF InterfacesTuple)
53 * $(LREF isInnerClass)
54 * $(LREF isNested)
55 * $(LREF MemberFunctionsTuple)
56 * $(LREF RepresentationTypeTuple)
57 * $(LREF TemplateArgsOf)
58 * $(LREF TemplateOf)
59 * $(LREF TransitiveBaseTypeTuple)
60 * ))
61 * $(TR $(TD Type Conversion) $(TD
62 * $(LREF CommonType)
63 * $(LREF AllImplicitConversionTargets)
64 * $(LREF ImplicitConversionTargets)
65 * $(LREF CopyTypeQualifiers)
66 * $(LREF CopyConstness)
67 * $(LREF isAssignable)
68 * $(LREF isCovariantWith)
69 * $(LREF isImplicitlyConvertible)
70 * $(LREF isQualifierConvertible)
71 * ))
72 * $(TR $(TD Type Constructors) $(TD
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 Unshared)
136 * $(LREF Unqual)
137 * $(LREF Unsigned)
138 * $(LREF ValueType)
139 * $(LREF Promoted)
140 * ))
141 * $(TR $(TD Misc) $(TD
142 * $(LREF lvalueOf)
143 * $(LREF rvalueOf)
144 * $(LREF Select)
145 * $(LREF select)
146 * ))
147 * $(TR $(TD User-Defined Attributes) $(TD
148 * $(LREF hasUDA)
149 * $(LREF getUDAs)
150 * $(LREF getSymbolsByUDA)
151 * ))
155 * Copyright: Copyright The D Language Foundation 2005 - 2009.
156 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
157 * Authors: $(HTTP digitalmars.com, Walter Bright),
158 * Tomasz Stachowiak (`isExpressions`),
159 * $(HTTP erdani.org, Andrei Alexandrescu),
160 * Shin Fujishiro,
161 * $(HTTP octarineparrot.com, Robert Clipsham),
162 * $(HTTP klickverbot.at, David Nadlinger),
163 * Kenji Hara,
164 * Shoichi Kato
165 * Source: $(PHOBOSSRC std/traits.d)
167 /* Copyright The D Language Foundation 2005 - 2009.
168 * Distributed under the Boost Software License, Version 1.0.
169 * (See accompanying file LICENSE_1_0.txt or copy at
170 * http://www.boost.org/LICENSE_1_0.txt)
172 module std.traits;
174 import std.meta : AliasSeq, allSatisfy, anySatisfy, ApplyLeft;
176 // Legacy inheritance from std.typetuple
177 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797
178 import std.meta : staticMapMeta = staticMap;
179 // TODO: find a way to trigger deprecation warnings
180 //deprecated("staticMap is part of std.meta: Please import std.meta")
181 alias staticMap = staticMapMeta;
183 ///////////////////////////////////////////////////////////////////////////////
184 // Type lists
185 ///////////////////////////////////////////////////////////////////////////////
187 private
189 static if (is(ucent))
191 alias CentTypeList = AliasSeq!(cent, ucent);
192 alias SignedCentTypeList = AliasSeq!(cent);
193 alias UnsignedCentTypeList = AliasSeq!(ucent);
195 else
197 alias CentTypeList = AliasSeq!();
198 alias SignedCentTypeList = AliasSeq!();
199 alias UnsignedCentTypeList = AliasSeq!();
202 alias IntegralTypeList = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList);
203 alias SignedIntTypeList = AliasSeq!(byte, short, int, long, SignedCentTypeList);
204 alias UnsignedIntTypeList = AliasSeq!(ubyte, ushort, uint, ulong, UnsignedCentTypeList);
205 alias FloatingPointTypeList = AliasSeq!(float, double, real);
206 alias ImaginaryTypeList = AliasSeq!(ifloat, idouble, ireal);
207 alias ComplexTypeList = AliasSeq!(cfloat, cdouble, creal);
208 alias NumericTypeList = AliasSeq!(IntegralTypeList, FloatingPointTypeList);
209 alias CharTypeList = AliasSeq!(char, wchar, dchar);
213 * Params:
214 * T = The type to qualify
215 * Returns:
216 * `T` with the `inout` qualifier added.
218 alias InoutOf(T) = inout(T);
221 @safe unittest
223 static assert(is(InoutOf!(int) == inout int));
224 static assert(is(InoutOf!(inout int) == inout int));
225 static assert(is(InoutOf!(const int) == inout const int));
226 static assert(is(InoutOf!(shared int) == inout shared int));
230 * Params:
231 * T = The type to qualify
232 * Returns:
233 * `T` with the `const` qualifier added.
235 alias ConstOf(T) = const(T);
238 @safe unittest
240 static assert(is(ConstOf!(int) == const int));
241 static assert(is(ConstOf!(const int) == const int));
242 static assert(is(ConstOf!(inout int) == const inout int));
243 static assert(is(ConstOf!(shared int) == const shared int));
247 * Params:
248 * T = The type to qualify
249 * Returns:
250 * `T` with the `shared` qualifier added.
252 alias SharedOf(T) = shared(T);
255 @safe unittest
257 static assert(is(SharedOf!(int) == shared int));
258 static assert(is(SharedOf!(shared int) == shared int));
259 static assert(is(SharedOf!(inout int) == shared inout int));
260 static assert(is(SharedOf!(immutable int) == shared immutable int));
264 * Params:
265 * T = The type to qualify
266 * Returns:
267 * `T` with the `inout` and `shared` qualifiers added.
269 alias SharedInoutOf(T) = shared(inout(T));
272 @safe unittest
274 static assert(is(SharedInoutOf!(int) == shared inout int));
275 static assert(is(SharedInoutOf!(int) == inout shared int));
277 static assert(is(SharedInoutOf!(const int) == shared inout const int));
278 static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int));
282 * Params:
283 * T = The type to qualify
284 * Returns:
285 * `T` with the `const` and `shared` qualifiers added.
287 alias SharedConstOf(T) = shared(const(T));
290 @safe unittest
292 static assert(is(SharedConstOf!(int) == shared const int));
293 static assert(is(SharedConstOf!(int) == const shared int));
295 static assert(is(SharedConstOf!(inout int) == shared inout const int));
296 // immutable variables are implicitly shared and const
297 static assert(is(SharedConstOf!(immutable int) == immutable int));
301 * Params:
302 * T = The type to qualify
303 * Returns:
304 * `T` with the `const`, `shared`, and `inout` qualifiers added.
306 alias SharedConstInoutOf(T) = shared(const(inout(T)));
309 @safe unittest
311 static assert(is(SharedConstInoutOf!(int) == shared const inout int));
312 static assert(is(SharedConstInoutOf!(int) == const shared inout int));
313 static assert(is(SharedConstInoutOf!(inout int) == shared inout const int));
314 // immutable variables are implicitly shared and const
315 static assert(is(SharedConstInoutOf!(immutable int) == immutable int));
319 * Params:
320 * T = The type to qualify
321 * Returns:
322 * `T` with the `immutable` qualifier added.
324 alias ImmutableOf(T) = immutable(T);
327 @safe unittest
329 static assert(is(ImmutableOf!(int) == immutable int));
330 static assert(is(ImmutableOf!(const int) == immutable int));
331 static assert(is(ImmutableOf!(inout int) == immutable int));
332 static assert(is(ImmutableOf!(shared int) == immutable int));
335 @safe unittest
337 static assert(is( InoutOf!int == inout int));
338 static assert(is( ConstOf!int == const int));
339 static assert(is( SharedOf!int == shared int));
340 static assert(is(SharedInoutOf!int == shared inout int));
341 static assert(is(SharedConstOf!int == shared const int));
342 static assert(is( ImmutableOf!int == immutable int));
346 * Gives a template that can be used to apply the same
347 * attributes that are on the given type `T`. E.g. passing
348 * `inout shared int` will return `SharedInoutOf`.
350 * Params:
351 * T = the type to check qualifiers from
352 * Returns:
353 * The qualifier template from the given type `T`
355 template QualifierOf(T)
357 static if (is(immutable T == T))
359 alias QualifierOf = ImmutableOf;
361 else
363 private enum quals = is(const T == T) | (is(inout T == T) << 1) | (is(shared T == T) << 2);
364 static if (quals == 0) { import std.meta : Alias; alias QualifierOf = Alias; }
365 else static if (quals == 1) alias QualifierOf = ConstOf;
366 else static if (quals == 2) alias QualifierOf = InoutOf;
367 else static if (quals == 3) alias QualifierOf = ConstInoutOf;
368 else static if (quals == 4) alias QualifierOf = SharedOf;
369 else static if (quals == 5) alias QualifierOf = SharedConstOf;
370 else static if (quals == 6) alias QualifierOf = SharedInoutOf;
371 else alias QualifierOf = SharedConstInoutOf;
376 @safe unittest
378 static assert(__traits(isSame, QualifierOf!(shared const inout int), SharedConstInoutOf));
379 static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf));
380 static assert(__traits(isSame, QualifierOf!(shared int), SharedOf));
381 static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf));
382 import std.meta : Alias;
383 static assert(__traits(isSame, QualifierOf!(int), Alias));
386 @safe unittest
388 alias Qual1 = QualifierOf!( int); static assert(is(Qual1!long == long));
389 alias Qual2 = QualifierOf!( inout int); static assert(is(Qual2!long == inout long));
390 alias Qual3 = QualifierOf!( const int); static assert(is(Qual3!long == const long));
391 alias Qual4 = QualifierOf!(shared int); static assert(is(Qual4!long == shared long));
392 alias Qual5 = QualifierOf!(shared inout int); static assert(is(Qual5!long == shared inout long));
393 alias Qual6 = QualifierOf!(shared const int); static assert(is(Qual6!long == shared const long));
394 alias Qual7 = QualifierOf!( immutable int); static assert(is(Qual7!long == immutable long));
397 version (StdUnittest)
399 import std.meta : Alias;
400 alias TypeQualifierList = AliasSeq!(Alias, ConstOf, SharedOf, SharedConstOf, ImmutableOf);
402 struct SubTypeOf(T)
404 T val;
405 alias val this;
409 private alias parentOf(alias sym) = Identity!(__traits(parent, sym));
410 private alias parentOf(alias sym : T!Args, alias T, Args...) = Identity!(__traits(parent, T));
413 * Get the full package name for the given symbol.
415 template packageName(alias T)
417 import std.algorithm.searching : startsWith;
419 enum bool isNotFunc = !isSomeFunction!(T);
421 static if (__traits(compiles, parentOf!T))
422 enum parent = packageName!(parentOf!T);
423 else
424 enum string parent = null;
426 static if (isNotFunc && T.stringof.startsWith("package "))
427 enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $];
428 else static if (parent)
429 enum packageName = parent;
430 else
431 static assert(false, T.stringof ~ " has no parent");
435 @safe unittest
437 static assert(packageName!packageName == "std");
440 @safe unittest
442 import std.array;
444 static assert(packageName!std == "std");
445 static assert(packageName!(std.traits) == "std"); // this module
446 static assert(packageName!packageName == "std"); // symbol in this module
447 static assert(packageName!(std.array) == "std"); // other module from same package
449 import core.sync.barrier; // local import
450 static assert(packageName!core == "core");
451 static assert(packageName!(core.sync) == "core.sync");
452 static assert(packageName!Barrier == "core.sync");
454 struct X12287(T) { T i; }
455 static assert(packageName!(X12287!int.i) == "std");
458 version (none) @safe unittest //Please uncomment me when changing packageName to test global imports
460 import core.sync.barrier; // global import
461 static assert(packageName!core == "core");
462 static assert(packageName!(core.sync) == "core.sync");
463 static assert(packageName!Barrier == "core.sync");
467 @safe unittest
469 static assert(packageName!moduleName == "std");
472 // https://issues.dlang.org/show_bug.cgi?id=13741
473 @safe unittest
475 import std.ascii : isWhite;
476 static assert(packageName!(isWhite) == "std");
478 struct Foo{void opCall(int){}}
479 static assert(packageName!(Foo.opCall) == "std");
481 @property void function(int) vf;
482 static assert(packageName!(vf) == "std");
486 * Get the module name (including package) for the given symbol.
488 template moduleName(alias T)
490 import std.algorithm.searching : startsWith;
492 enum bool isNotFunc = !isSomeFunction!(T);
494 static if (isNotFunc)
495 static assert(!T.stringof.startsWith("package "),
496 "cannot get the module name for a package");
498 static if (isNotFunc && T.stringof.startsWith("module "))
500 static if (__traits(compiles, packageName!T))
501 enum packagePrefix = packageName!T ~ '.';
502 else
503 enum packagePrefix = "";
505 enum moduleName = packagePrefix ~ T.stringof[7..$];
507 else
508 alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE
512 @safe unittest
514 static assert(moduleName!moduleName == "std.traits");
517 @safe unittest
519 import std.array;
521 static assert(!__traits(compiles, moduleName!std));
522 static assert(moduleName!(std.traits) == "std.traits"); // this module
523 static assert(moduleName!moduleName == "std.traits"); // symbol in this module
524 static assert(moduleName!(std.array) == "std.array"); // other module
525 static assert(moduleName!(std.array.array) == "std.array"); // symbol in other module
527 import core.sync.barrier; // local import
528 static assert(!__traits(compiles, moduleName!(core.sync)));
529 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
530 static assert(moduleName!Barrier == "core.sync.barrier");
532 struct X12287(T) { T i; }
533 static assert(moduleName!(X12287!int.i) == "std.traits");
536 // https://issues.dlang.org/show_bug.cgi?id=13741
537 @safe unittest
539 import std.ascii : isWhite;
540 static assert(moduleName!(isWhite) == "std.ascii");
542 struct Foo{void opCall(int){}}
543 static assert(moduleName!(Foo.opCall) == "std.traits");
545 @property void function(int) vf;
546 static assert(moduleName!(vf) == "std.traits");
549 version (none) @safe unittest //Please uncomment me when changing moduleName to test global imports
551 import core.sync.barrier; // global import
552 static assert(!__traits(compiles, moduleName!(core.sync)));
553 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
554 static assert(moduleName!Barrier == "core.sync.barrier");
557 /***
558 * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.
560 Example:
561 -----------------
562 module myModule;
563 struct MyStruct {}
564 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
565 -----------------
567 enum fullyQualifiedName(T) = fqnType!(T, false, false, false, false);
569 /// ditto
570 enum fullyQualifiedName(alias T) = fqnSym!(T);
573 @safe unittest
575 static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
578 version (StdUnittest)
580 // Used for both fqnType and fqnSym unittests
581 private struct QualifiedNameTests
583 struct Inner
585 bool value;
588 ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 );
589 ref const(Inner[string]) retfunc( return ref Inner var1 );
590 Inner inoutFunc(inout Inner) inout;
591 shared(const(Inner[string])[]) data;
592 const Inner delegate(double, string) @safe nothrow deleg;
593 inout(int) delegate(inout int) inout inoutDeleg;
594 Inner function(out double, string) funcPtr;
595 extern(C) Inner function(double, string) cFuncPtr;
597 extern(C) void cVarArg(int, ...);
598 void dVarArg(...);
599 void dVarArg2(int, ...);
600 void typesafeVarArg(int[] ...);
602 Inner[] array;
603 Inner[16] sarray;
604 Inner[Inner] aarray;
605 const(Inner[const(Inner)]) qualAarray;
607 shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg;
609 struct Data(T) { int x; }
610 void tfunc(T...)(T args) {}
612 template Inst(alias A) { int x; }
614 class Test12309(T, int x, string s) {}
617 private enum QualifiedEnum
619 a = 42
623 private template fqnSym(alias T : X!A, alias X, A...)
625 template fqnTuple(T...)
627 static if (T.length == 0)
628 enum fqnTuple = "";
629 else static if (T.length == 1)
631 static if (isExpressionTuple!T)
632 enum fqnTuple = T[0].stringof;
633 else
634 enum fqnTuple = fullyQualifiedName!(T[0]);
636 else
637 enum fqnTuple = fqnTuple!(T[0]) ~ ", " ~ fqnTuple!(T[1 .. $]);
640 enum fqnSym =
641 fqnSym!(__traits(parent, X)) ~
642 '.' ~ __traits(identifier, X) ~ "!(" ~ fqnTuple!A ~ ")";
645 private template fqnSym(alias T)
647 static if (__traits(compiles, __traits(parent, T)) && !__traits(isSame, T, __traits(parent, T)))
648 enum parentPrefix = fqnSym!(__traits(parent, T)) ~ ".";
649 else
650 enum parentPrefix = null;
652 static string adjustIdent(string s)
654 import std.algorithm.searching : findSplit, skipOver;
656 if (s.skipOver("package ") || s.skipOver("module "))
657 return s;
658 return s.findSplit("(")[0];
660 enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
663 @safe unittest
665 alias fqn = fullyQualifiedName;
667 // Make sure those 2 are the same
668 static assert(fqnSym!fqn == fqn!fqn);
670 static assert(fqn!fqn == "std.traits.fullyQualifiedName");
672 alias qnTests = QualifiedNameTests;
673 enum prefix = "std.traits.QualifiedNameTests.";
674 static assert(fqn!(qnTests.Inner) == prefix ~ "Inner");
675 static assert(fqn!(qnTests.func) == prefix ~ "func");
676 static assert(fqn!(qnTests.Data!int) == prefix ~ "Data!(int)");
677 static assert(fqn!(qnTests.Data!int.x) == prefix ~ "Data!(int).x");
678 static assert(fqn!(qnTests.tfunc!(int[])) == prefix ~ "tfunc!(int[])");
679 static assert(fqn!(qnTests.Inst!(Object)) == prefix ~ "Inst!(object.Object)");
680 static assert(fqn!(qnTests.Inst!(Object).x) == prefix ~ "Inst!(object.Object).x");
682 static assert(fqn!(qnTests.Test12309!(int, 10, "str"))
683 == prefix ~ "Test12309!(int, 10, \"str\")");
685 import core.sync.barrier;
686 static assert(fqn!Barrier == "core.sync.barrier.Barrier");
689 @safe unittest
691 struct TemplatedStruct()
693 enum foo = 0;
695 alias TemplatedStructAlias = TemplatedStruct;
696 assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo));
699 private template fqnType(T,
700 bool alreadyConst, bool alreadyImmutable, bool alreadyShared, bool alreadyInout)
702 // Convenience tags
703 enum {
704 _const = 0,
705 _immutable = 1,
706 _shared = 2,
707 _inout = 3
710 alias qualifiers = AliasSeq!(is(T == const), is(T == immutable), is(T == shared), is(T == inout));
711 alias noQualifiers = AliasSeq!(false, false, false, false);
713 string storageClassesString(uint psc)() @property
715 import std.conv : text;
717 alias PSC = ParameterStorageClass;
719 return text(
720 psc & PSC.scope_ ? "scope " : "",
721 psc & PSC.return_ ? "return " : "",
722 psc & PSC.in_ ? "in " : "",
723 psc & PSC.out_ ? "out " : "",
724 psc & PSC.ref_ ? "ref " : "",
725 psc & PSC.lazy_ ? "lazy " : "",
729 string parametersTypeString(T)() @property
731 alias parameters = Parameters!(T);
732 alias parameterStC = ParameterStorageClassTuple!(T);
734 enum variadic = variadicFunctionStyle!T;
735 static if (variadic == Variadic.no)
736 enum variadicStr = "";
737 else static if (variadic == Variadic.c)
738 enum variadicStr = ", ...";
739 else static if (variadic == Variadic.d)
740 enum variadicStr = parameters.length ? ", ..." : "...";
741 else static if (variadic == Variadic.typesafe)
742 enum variadicStr = " ...";
743 else
744 static assert(0, "New variadic style has been added, please update fullyQualifiedName implementation");
746 static if (parameters.length)
748 import std.algorithm.iteration : map;
749 import std.array : join;
750 import std.meta : staticMap;
751 import std.range : zip;
753 string result = join(
754 map!(a => (a[0] ~ a[1]))(
755 zip([staticMap!(storageClassesString, parameterStC)],
756 [staticMap!(fullyQualifiedName, parameters)])
758 ", "
761 return result ~= variadicStr;
763 else
764 return variadicStr;
767 string linkageString(T)() @property
769 enum linkage = functionLinkage!T;
771 if (linkage != "D")
772 return "extern(" ~ linkage ~ ") ";
773 else
774 return "";
777 string functionAttributeString(T)() @property
779 alias FA = FunctionAttribute;
780 enum attrs = functionAttributes!T;
782 static if (attrs == FA.none)
783 return "";
784 else
785 return
786 (attrs & FA.pure_ ? " pure" : "")
787 ~ (attrs & FA.nothrow_ ? " nothrow" : "")
788 ~ (attrs & FA.ref_ ? " ref" : "")
789 ~ (attrs & FA.property ? " @property" : "")
790 ~ (attrs & FA.trusted ? " @trusted" : "")
791 ~ (attrs & FA.safe ? " @safe" : "")
792 ~ (attrs & FA.nogc ? " @nogc" : "")
793 ~ (attrs & FA.return_ ? " return" : "")
794 ~ (attrs & FA.live ? " @live" : "");
797 string addQualifiers(string typeString,
798 bool addConst, bool addImmutable, bool addShared, bool addInout)
800 auto result = typeString;
801 if (addShared)
803 result = "shared(" ~ result ~")";
805 if (addConst || addImmutable || addInout)
807 result = (addConst ? "const" : addImmutable ? "immutable" : "inout")
808 ~ "(" ~ result ~ ")";
810 return result;
813 // Convenience template to avoid copy-paste
814 template chain(string current)
816 enum chain = addQualifiers(current,
817 qualifiers[_const] && !alreadyConst,
818 qualifiers[_immutable] && !alreadyImmutable,
819 qualifiers[_shared] && !alreadyShared,
820 qualifiers[_inout] && !alreadyInout);
823 static if (is(T == string))
825 enum fqnType = "string";
827 else static if (is(T == wstring))
829 enum fqnType = "wstring";
831 else static if (is(T == dstring))
833 enum fqnType = "dstring";
835 else static if (is(T == typeof(null)))
837 enum fqnType = "typeof(null)";
839 else static if (isBasicType!T && !is(T == enum))
841 enum fqnType = chain!((Unqual!T).stringof);
843 else static if (isAggregateType!T || is(T == enum))
845 enum fqnType = chain!(fqnSym!T);
847 else static if (isStaticArray!T)
849 import std.conv : to;
850 enum fqnType = chain!(
851 fqnType!(typeof(T.init[0]), qualifiers) ~ "[" ~ to!string(T.length) ~ "]"
854 else static if (isArray!T)
856 enum fqnType = chain!(
857 fqnType!(typeof(T.init[0]), qualifiers) ~ "[]"
860 else static if (isAssociativeArray!T)
862 enum fqnType = chain!(
863 fqnType!(ValueType!T, qualifiers) ~ '[' ~ fqnType!(KeyType!T, noQualifiers) ~ ']'
866 else static if (isSomeFunction!T)
868 static if (is(T F == delegate))
870 enum qualifierString =
871 (is(F == shared) ? " shared" : "")
872 ~ (is(F == inout) ? " inout" :
873 is(F == immutable) ? " immutable" :
874 is(F == const) ? " const" : "");
875 enum fqnType = chain!(
876 linkageString!T
877 ~ fqnType!(ReturnType!T, noQualifiers)
878 ~ " delegate(" ~ parametersTypeString!(T) ~ ")"
879 ~ functionAttributeString!T
880 ~ qualifierString
883 else
885 enum fqnType = chain!(
886 linkageString!T
887 ~ fqnType!(ReturnType!T, noQualifiers)
888 ~ (isFunctionPointer!T ? " function(" : "(")
889 ~ parametersTypeString!(T) ~ ")"
890 ~ functionAttributeString!T
894 else static if (is(T == U*, U))
896 enum fqnType = chain!(
897 fqnType!(U, qualifiers) ~ "*"
900 else static if (is(T : __vector(V[N]), V, size_t N))
902 import std.conv : to;
903 enum fqnType = chain!(
904 "__vector(" ~ fqnType!(V, qualifiers) ~ "[" ~ N.to!string ~ "])"
907 else
908 // In case something is forgotten
909 static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string");
912 @safe unittest
914 import std.format : format;
915 alias fqn = fullyQualifiedName;
917 // Verify those 2 are the same for simple case
918 alias Ambiguous = const(QualifiedNameTests.Inner);
919 static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false));
921 // Main tests
922 enum inner_name = "std.traits.QualifiedNameTests.Inner";
923 with (QualifiedNameTests)
925 // Special cases
926 static assert(fqn!(string) == "string");
927 static assert(fqn!(wstring) == "wstring");
928 static assert(fqn!(dstring) == "dstring");
929 static assert(fqn!(typeof(null)) == "typeof(null)");
930 static assert(fqn!(void) == "void");
931 static assert(fqn!(const(void)) == "const(void)");
932 static assert(fqn!(shared(void)) == "shared(void)");
933 static assert(fqn!(shared const(void)) == "const(shared(void))");
934 static assert(fqn!(shared inout(void)) == "inout(shared(void))");
935 static assert(fqn!(shared inout const(void)) == "const(shared(void))");
936 static assert(fqn!(inout(void)) == "inout(void)");
937 static assert(fqn!(inout const(void)) == "const(void)");
938 static assert(fqn!(immutable(void)) == "immutable(void)");
940 // Basic qualified name
941 static assert(fqn!(Inner) == inner_name);
942 static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type
943 static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol
945 // Array types
946 static assert(fqn!(typeof(array)) == format("%s[]", inner_name));
947 static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name));
948 static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name));
950 // qualified key for AA
951 static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name));
953 // Qualified composed data types
954 static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name));
956 // Function types + function attributes
957 static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref",
958 inner_name, inner_name));
959 static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name));
960 static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name));
961 static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name));
962 static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout");
963 static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name));
964 static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name));
966 // Delegate type with qualified function type
967 static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~
968 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name));
970 // Variable argument function types
971 static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)");
972 static assert(fqn!(typeof(dVarArg)) == "void(...)");
973 static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)");
974 static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)");
976 // SIMD vector
977 static if (is(__vector(float[4])))
979 static assert(fqn!(__vector(float[4])) == "__vector(float[4])");
984 /***
985 * Get the type of the return value from a function,
986 * a pointer to function, a delegate, a struct
987 * with an opCall, a pointer to a struct with an opCall,
988 * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
989 * is not part of a type, but the attribute of the function
990 * (see template $(LREF functionAttributes)).
992 * $(NOTE To reduce template instantiations, consider instead using
993 * $(D typeof(() { return func(args); } ())) if the argument types are known or
994 * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
996 template ReturnType(alias func)
997 if (isCallable!func)
999 static if (is(FunctionTypeOf!func R == return))
1000 alias ReturnType = R;
1001 else
1002 static assert(0, "argument has no return type");
1006 @safe unittest
1008 int foo();
1009 ReturnType!foo x; // x is declared as int
1012 @safe unittest
1014 struct G
1016 int opCall (int i) { return 1;}
1019 alias ShouldBeInt = ReturnType!G;
1020 static assert(is(ShouldBeInt == int));
1022 G g;
1023 static assert(is(ReturnType!g == int));
1025 G* p;
1026 alias pg = ReturnType!p;
1027 static assert(is(pg == int));
1029 class C
1031 int opCall (int i) { return 1;}
1034 static assert(is(ReturnType!C == int));
1036 C c;
1037 static assert(is(ReturnType!c == int));
1039 class Test
1041 int prop() @property { return 0; }
1043 alias R_Test_prop = ReturnType!(Test.prop);
1044 static assert(is(R_Test_prop == int));
1046 alias R_dglit = ReturnType!((int a) { return a; });
1047 static assert(is(R_dglit == int));
1050 /***
1051 Get, as a tuple, the types of the parameters to a function, a pointer
1052 to function, a delegate, a struct with an `opCall`, a pointer to a
1053 struct with an `opCall`, or a class with an `opCall`.
1055 template Parameters(alias func)
1056 if (isCallable!func)
1058 static if (is(FunctionTypeOf!func P == function))
1059 alias Parameters = P;
1060 else
1061 static assert(0, "argument has no parameters");
1065 @safe unittest
1067 int foo(int, long);
1068 void bar(Parameters!foo); // declares void bar(int, long);
1069 void abc(Parameters!foo[1]); // declares void abc(long);
1073 * Alternate name for $(LREF Parameters), kept for legacy compatibility.
1075 alias ParameterTypeTuple = Parameters;
1077 @safe unittest
1079 int foo(int i, bool b) { return 0; }
1080 static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool)));
1081 static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool)));
1083 struct S { real opCall(real r, int i) { return 0.0; } }
1084 S s;
1085 static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int)));
1086 static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int)));
1087 static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int)));
1089 class Test
1091 int prop() @property { return 0; }
1093 alias P_Test_prop = ParameterTypeTuple!(Test.prop);
1094 static assert(P_Test_prop.length == 0);
1096 alias P_dglit = ParameterTypeTuple!((int a){});
1097 static assert(P_dglit.length == 1);
1098 static assert(is(P_dglit[0] == int));
1102 Returns the number of arguments of function `func`.
1103 arity is undefined for variadic functions.
1105 template arity(alias func)
1106 if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
1108 enum size_t arity = Parameters!func.length;
1112 @safe unittest
1114 void foo(){}
1115 static assert(arity!foo == 0);
1116 void bar(uint){}
1117 static assert(arity!bar == 1);
1118 void variadicFoo(uint...){}
1119 static assert(!__traits(compiles, arity!variadicFoo));
1122 // https://issues.dlang.org/show_bug.cgi?id=11389
1123 @safe unittest
1125 alias TheType = size_t function( string[] );
1126 static assert(arity!TheType == 1);
1130 Get a tuple of the storage classes of a function's parameters.
1131 Params:
1132 func = function symbol or type of function, delegate, or pointer to function
1133 Returns:
1134 A tuple of ParameterStorageClass bits
1136 enum ParameterStorageClass : uint
1139 * These flags can be bitwise OR-ed together to represent complex storage
1140 * class.
1142 none = 0x00,
1143 in_ = 0x01, /// ditto
1144 ref_ = 0x02, /// ditto
1145 out_ = 0x04, /// ditto
1146 lazy_ = 0x08, /// ditto
1147 scope_ = 0x10, /// ditto
1148 return_ = 0x20, /// ditto
1151 /// ditto
1152 template ParameterStorageClassTuple(alias func)
1153 if (isCallable!func)
1155 alias Func = FunctionTypeOf!func;
1157 static if (is(Func PT == __parameters))
1159 alias ParameterStorageClassTuple = AliasSeq!();
1160 static foreach (i; 0 .. PT.length)
1162 ParameterStorageClassTuple = AliasSeq!(ParameterStorageClassTuple,
1163 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)));
1166 else
1168 static assert(0, func.stringof, " is not a function");
1169 alias ParameterStorageClassTuple = AliasSeq!();
1174 @safe unittest
1176 alias STC = ParameterStorageClass; // shorten the enum name
1178 void func(ref int ctx, out real result, in real param, void* ptr)
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_);
1185 version (none)
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_);
1193 static assert(pstc[3] == STC.none);
1197 Convert the result of $(DDSUBLINK spec/traits, getParameterStorageClasses, `__traits(getParameterStorageClasses)`)
1198 to $(LREF ParameterStorageClass) `enum`s.
1200 Params:
1201 Attribs = The return value of `__traits(getParameterStorageClasses)`
1202 Returns:
1203 The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s.
1205 template extractParameterStorageClassFlags(Attribs...)
1207 enum ParameterStorageClass extractParameterStorageClassFlags = ()
1209 auto result = ParameterStorageClass.none;
1210 static if (Attribs.length > 0)
1212 static foreach (attrib; Attribs)
1214 final switch (attrib) with (ParameterStorageClass)
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;
1224 /* Mimic behavor of original version of ParameterStorageClassTuple()
1225 * to avoid breaking existing code.
1227 if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
1228 result = ParameterStorageClass.return_;
1230 return result;
1231 }();
1235 @safe unittest
1237 static void func(ref int ctx, out real result);
1239 enum param1 = extractParameterStorageClassFlags!(
1240 __traits(getParameterStorageClasses, func, 0)
1242 static assert(param1 == ParameterStorageClass.ref_);
1244 enum param2 = extractParameterStorageClassFlags!(
1245 __traits(getParameterStorageClasses, func, 1)
1247 static assert(param2 == ParameterStorageClass.out_);
1249 enum param3 = extractParameterStorageClassFlags!(
1250 __traits(getParameterStorageClasses, func, 0),
1251 __traits(getParameterStorageClasses, func, 1)
1253 static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_));
1256 @safe unittest
1258 alias STC = ParameterStorageClass;
1260 void noparam() {}
1261 static assert(ParameterStorageClassTuple!noparam.length == 0);
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_);
1273 interface Test
1275 void test_const(int) const;
1276 void test_sharedconst(int) shared const;
1278 Test testi;
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);
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);
1288 alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {});
1289 static assert(dglit_pstc.length == 1);
1290 static assert(dglit_pstc[0] == STC.ref_);
1292 // https://issues.dlang.org/show_bug.cgi?id=9317
1293 static inout(int) func(inout int param) { return param; }
1294 static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none);
1297 @safe unittest
1299 // https://issues.dlang.org/show_bug.cgi?id=14253
1300 static struct Foo {
1301 ref Foo opAssign(ref Foo rhs) return { return this; }
1304 alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]);
1309 Get, as a tuple, the identifiers of the parameters to a function symbol.
1311 template ParameterIdentifierTuple(alias func)
1312 if (isCallable!func)
1314 static if (is(FunctionTypeOf!func PT == __parameters))
1316 alias ParameterIdentifierTuple = AliasSeq!();
1317 static foreach (i; 0 .. PT.length)
1319 static if (!isFunctionPointer!func && !isDelegate!func
1320 // Unnamed parameters yield CT error.
1321 && is(typeof(__traits(identifier, PT[i .. i+1])))
1322 // Filter out unnamed args, which look like (Type) instead of (Type name).
1323 && PT[i].stringof != PT[i .. i+1].stringof[1..$-1])
1325 ParameterIdentifierTuple = AliasSeq!(ParameterIdentifierTuple,
1326 __traits(identifier, PT[i .. i+1]));
1328 else
1330 ParameterIdentifierTuple = AliasSeq!(ParameterIdentifierTuple, "");
1334 else
1336 static assert(0, func.stringof ~ " is not a function");
1337 // avoid pointless errors
1338 alias ParameterIdentifierTuple = AliasSeq!();
1343 @safe unittest
1345 int foo(int num, string name, int);
1346 static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
1349 // https://issues.dlang.org/show_bug.cgi?id=19456
1350 @safe unittest
1352 struct SomeType {}
1353 void foo(SomeType);
1354 void bar(int);
1355 static assert([ParameterIdentifierTuple!foo] == [""]);
1356 static assert([ParameterIdentifierTuple!bar] == [""]);
1359 @safe unittest
1361 alias PIT = ParameterIdentifierTuple;
1363 void bar(int num, string name, int[] array){}
1364 static assert([PIT!bar] == ["num", "name", "array"]);
1366 // might be changed in the future?
1367 void function(int num, string name) fp;
1368 static assert([PIT!fp] == ["", ""]);
1370 // might be changed in the future?
1371 void delegate(int num, string name, int[long] aa) dg;
1372 static assert([PIT!dg] == ["", "", ""]);
1374 interface Test
1376 @property string getter();
1377 @property void setter(int a);
1378 Test method(int a, long b, string c);
1380 static assert([PIT!(Test.getter)] == []);
1381 static assert([PIT!(Test.setter)] == ["a"]);
1382 static assert([PIT!(Test.method)] == ["a", "b", "c"]);
1385 // depends on internal
1386 void baw(int, string, int[]){}
1387 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1389 // depends on internal
1390 void baz(AliasSeq!(int, string, int[]) args){}
1391 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1397 Get, as a tuple, the default values of the parameters to a function symbol.
1398 If a parameter doesn't have the default value, `void` is returned instead.
1400 template ParameterDefaults(alias func)
1401 if (isCallable!func)
1403 alias param_names = ParameterIdentifierTuple!func;
1404 static if (is(FunctionTypeOf!(func) PT == __parameters))
1406 template Get(size_t i)
1408 // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1409 // To avoid a name clash, generate local names that are distinct
1410 // from the parameter name, and mix them in.
1411 enum name = param_names[i];
1412 enum args = "args" ~ (name == "args" ? "_" : "");
1413 enum val = "val" ~ (name == "val" ? "_" : "");
1414 enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1415 enum hasDefaultArg = mixin("(PT[i .. i+1] ", args, ") => true");
1416 static if (is(typeof(hasDefaultArg())))
1418 enum get = mixin("(return scope PT[i .. i+1] ", args, ")
1420 // If the parameter is lazy, we force it to be evaluated
1421 // like this.
1422 auto ", val, " = ", args, "[0];
1423 auto ", ptr, " = &", val, ";
1424 return *", ptr, ";
1425 }");
1426 enum Get = get();
1428 else
1429 alias Get = void;
1430 // If default arg doesn't exist, returns void instead.
1432 alias ParameterDefaults = AliasSeq!();
1433 static foreach (i; 0 .. PT.length)
1435 ParameterDefaults = AliasSeq!(ParameterDefaults,
1436 Get!i);
1439 else
1441 static assert(0, func.stringof ~ " is not a function");
1442 // avoid pointless errors
1443 alias ParameterDefaults = AliasSeq!();
1448 @safe unittest
1450 int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
1451 static assert(is(ParameterDefaults!foo[0] == void));
1452 static assert( ParameterDefaults!foo[1] == "hello");
1453 static assert( ParameterDefaults!foo[2] == [1,2,3]);
1454 static assert( ParameterDefaults!foo[3] == 0);
1457 // https://issues.dlang.org/show_bug.cgi?id=17192
1458 @safe unittest
1460 static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1461 int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1464 alias Voids = ParameterDefaults!func;
1465 static assert(Voids.length == 12);
1466 static foreach (V; Voids) static assert(is(V == void));
1469 // https://issues.dlang.org/show_bug.cgi?id=20182
1470 @safe pure nothrow @nogc unittest
1472 struct S
1474 this(ref S) {}
1477 static assert(__traits(compiles, ParameterDefaults!(S.__ctor)));
1481 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1483 alias ParameterDefaultValueTuple = ParameterDefaults;
1485 @safe unittest
1487 alias PDVT = ParameterDefaultValueTuple;
1489 void bar(int n = 1, string s = "hello"){}
1490 static assert(PDVT!bar.length == 2);
1491 static assert(PDVT!bar[0] == 1);
1492 static assert(PDVT!bar[1] == "hello");
1493 static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello"))));
1495 void baz(int x, int n = 1, string s = "hello"){}
1496 static assert(PDVT!baz.length == 3);
1497 static assert(is(PDVT!baz[0] == void));
1498 static assert( PDVT!baz[1] == 1);
1499 static assert( PDVT!baz[2] == "hello");
1500 static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello"))));
1502 // property functions return empty string
1503 // https://issues.dlang.org/show_bug.cgi?id=10800
1504 @property void foo(int x = 3) { }
1505 static assert(PDVT!foo.length == 1);
1506 static assert(PDVT!foo[0] == 3);
1507 static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3))));
1509 struct Colour
1511 ubyte a,r,g,b;
1513 static immutable Colour white = Colour(255,255,255,255);
1515 // https://issues.dlang.org/show_bug.cgi?id=8106
1516 void bug8106(Colour c = Colour.white) {}
1517 //pragma(msg, PDVT!bug8106);
1518 static assert(PDVT!bug8106[0] == Colour.white);
1519 // https://issues.dlang.org/show_bug.cgi?id=16582
1520 void bug16582(scope int* val = null) {}
1521 static assert(PDVT!bug16582[0] is null);
1526 Returns the FunctionAttribute mask for function `func`.
1528 See_Also:
1529 $(LREF hasFunctionAttributes)
1531 enum FunctionAttribute : uint
1534 * These flags can be bitwise OR-ed together to represent a complex attribute.
1536 none = 0,
1537 pure_ = 1 << 0, /// ditto
1538 nothrow_ = 1 << 1, /// ditto
1539 ref_ = 1 << 2, /// ditto
1540 property = 1 << 3, /// ditto
1541 trusted = 1 << 4, /// ditto
1542 safe = 1 << 5, /// ditto
1543 nogc = 1 << 6, /// ditto
1544 system = 1 << 7, /// ditto
1545 const_ = 1 << 8, /// ditto
1546 immutable_ = 1 << 9, /// ditto
1547 inout_ = 1 << 10, /// ditto
1548 shared_ = 1 << 11, /// ditto
1549 return_ = 1 << 12, /// ditto
1550 scope_ = 1 << 13, /// ditto
1551 live = 1 << 14, /// ditto
1554 /// ditto
1555 template functionAttributes(alias func)
1556 if (isCallable!func)
1558 // @bug: workaround for opCall
1559 alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
1560 func, Unqual!(FunctionTypeOf!func));
1562 enum FunctionAttribute functionAttributes =
1563 extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))();
1567 @safe unittest
1569 alias FA = FunctionAttribute; // shorten the enum name
1571 real func(real x) pure nothrow @safe
1573 return x;
1575 static assert(functionAttributes!func & FA.pure_);
1576 static assert(functionAttributes!func & FA.safe);
1577 static assert(!(functionAttributes!func & FA.trusted)); // not @trusted
1580 @system unittest
1582 alias FA = FunctionAttribute;
1584 struct S
1586 int noF() { return 0; }
1587 int constF() const { return 0; }
1588 int immutableF() immutable { return 0; }
1589 int inoutF() inout { return 0; }
1590 int sharedF() shared { return 0; }
1592 int x;
1593 ref int refF() return { return x; }
1594 int propertyF() @property { return 0; }
1595 int nothrowF() nothrow { return 0; }
1596 int nogcF() @nogc { return 0; }
1598 int systemF() @system { return 0; }
1599 int trustedF() @trusted { return 0; }
1600 int safeF() @safe { return 0; }
1602 int pureF() pure { return 0; }
1604 int liveF() @live { return 0; }
1607 static assert(functionAttributes!(S.noF) == FA.system);
1608 static assert(functionAttributes!(typeof(S.noF)) == FA.system);
1610 static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system));
1611 static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system));
1613 static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system));
1614 static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system));
1616 static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system));
1617 static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system));
1619 static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system));
1620 static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system));
1622 static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_));
1623 static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_));
1625 static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system));
1626 static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system));
1628 static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system));
1629 static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system));
1631 static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system));
1632 static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system));
1634 static assert(functionAttributes!(S.systemF) == FA.system);
1635 static assert(functionAttributes!(typeof(S.systemF)) == FA.system);
1637 static assert(functionAttributes!(S.trustedF) == FA.trusted);
1638 static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted);
1640 static assert(functionAttributes!(S.safeF) == FA.safe);
1641 static assert(functionAttributes!(typeof(S.safeF)) == FA.safe);
1643 static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system));
1644 static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system));
1646 static assert(functionAttributes!(S.liveF) == (FA.live | FA.system));
1647 static assert(functionAttributes!(typeof(S.liveF)) == (FA.live | FA.system));
1649 int pure_nothrow() nothrow pure;
1650 void safe_nothrow() @safe nothrow;
1651 static ref int static_ref_property() @property;
1652 ref int ref_property() @property;
1654 static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system));
1655 static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system));
1657 static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_));
1658 static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_));
1660 static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system));
1661 static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system));
1663 static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system));
1664 static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system));
1666 struct S2
1668 int pure_const() const pure { return 0; }
1669 int pure_sharedconst() const shared pure { return 0; }
1672 static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system));
1673 static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system));
1675 static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1676 static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1678 static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1679 static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1681 auto safeDel = delegate() @safe { };
1682 static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1683 static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1685 auto trustedDel = delegate() @trusted { };
1686 static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1687 static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1689 auto systemDel = delegate() @system { };
1690 static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1691 static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1694 private FunctionAttribute extractAttribFlags(Attribs...)()
1696 auto res = FunctionAttribute.none;
1698 static foreach (attrib; Attribs)
1700 switch (attrib) with (FunctionAttribute)
1702 case "pure": res |= pure_; break;
1703 case "nothrow": res |= nothrow_; break;
1704 case "ref": res |= ref_; break;
1705 case "@property": res |= property; break;
1706 case "@trusted": res |= trusted; break;
1707 case "@safe": res |= safe; break;
1708 case "@nogc": res |= nogc; break;
1709 case "@system": res |= system; break;
1710 case "const": res |= const_; break;
1711 case "immutable": res |= immutable_; break;
1712 case "inout": res |= inout_; break;
1713 case "shared": res |= shared_; break;
1714 case "return": res |= return_; break;
1715 case "scope": res |= scope_; break;
1716 case "@live": res |= live; break;
1717 default: assert(0, attrib);
1721 return res;
1725 Checks whether a function has the given attributes attached.
1727 Params:
1728 args = Function to check, followed by a
1729 variadic number of function attributes as strings
1731 Returns:
1732 `true`, if the function has the list of attributes attached and `false` otherwise.
1734 See_Also:
1735 $(LREF functionAttributes)
1737 template hasFunctionAttributes(args...)
1738 if (args.length > 0 && isCallable!(args[0])
1739 && allSatisfy!(isSomeString, typeof(args[1 .. $])))
1741 enum bool hasFunctionAttributes = {
1742 import std.algorithm.searching : canFind;
1743 import std.range : only;
1744 enum funcAttribs = only(__traits(getFunctionAttributes, args[0]));
1745 static foreach (attribute; args[1 .. $])
1747 if (!funcAttribs.canFind(attribute))
1748 return false;
1750 return true;
1751 }();
1755 @safe unittest
1757 real func(real x) pure nothrow @safe;
1758 static assert(hasFunctionAttributes!(func, "@safe", "pure"));
1759 static assert(!hasFunctionAttributes!(func, "@trusted"));
1761 // for templates attributes are automatically inferred
1762 bool myFunc(T)(T b)
1764 return !b;
1766 static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
1767 static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
1770 @system unittest
1772 struct S
1774 int noF();
1775 int constF() const;
1776 int immutableF() immutable;
1777 int inoutF() inout;
1778 int sharedF() shared;
1780 ref int refF() return;
1781 int propertyF() @property;
1782 int nothrowF() nothrow;
1783 int nogcF() @nogc;
1785 int systemF() @system;
1786 int trustedF() @trusted;
1787 int safeF() @safe;
1789 int pureF() pure;
1791 int liveF() @live;
1794 // true if no args passed
1795 static assert(hasFunctionAttributes!(S.noF));
1797 static assert(hasFunctionAttributes!(S.noF, "@system"));
1798 static assert(hasFunctionAttributes!(typeof(S.noF), "@system"));
1799 static assert(!hasFunctionAttributes!(S.noF, "@system", "pure"));
1801 static assert(hasFunctionAttributes!(S.constF, "const", "@system"));
1802 static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system"));
1803 static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc"));
1805 static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system"));
1806 static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system"));
1807 static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure"));
1809 static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system"));
1810 static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system"));
1811 static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure"));
1813 static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system"));
1814 static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system"));
1815 static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted"));
1817 static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return"));
1818 static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return"));
1819 static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure"));
1821 static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system"));
1822 static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system"));
1823 static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref"));
1825 static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system"));
1826 static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system"));
1827 static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted"));
1829 static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system"));
1830 static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system"));
1831 static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref"));
1833 static assert(hasFunctionAttributes!(S.systemF, "@system"));
1834 static assert(hasFunctionAttributes!(typeof(S.systemF), "@system"));
1835 static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref"));
1837 static assert(hasFunctionAttributes!(S.trustedF, "@trusted"));
1838 static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted"));
1839 static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe"));
1841 static assert(hasFunctionAttributes!(S.safeF, "@safe"));
1842 static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe"));
1843 static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow"));
1845 static assert(hasFunctionAttributes!(S.pureF, "pure", "@system"));
1846 static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system"));
1847 static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref"));
1849 static assert(hasFunctionAttributes!(S.liveF, "@live", "@system"));
1850 static assert(hasFunctionAttributes!(typeof(S.liveF), "@live", "@system"));
1851 static assert(!hasFunctionAttributes!(S.liveF, "@live", "@system", "ref"));
1853 int pure_nothrow() nothrow pure { return 0; }
1854 void safe_nothrow() @safe nothrow { }
1855 static ref int static_ref_property() @property { return *(new int); }
1856 ref int ref_property() @property { return *(new int); }
1858 static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe"));
1859 static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe"));
1860 static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted"));
1862 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow"));
1863 static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow"));
1864 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure"));
1865 static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted"));
1867 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe"));
1868 static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe"));
1869 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow"));
1870 static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc"));
1872 static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe"));
1873 static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe"));
1874 static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc"));
1876 struct S2
1878 int pure_const() const pure { return 0; }
1879 int pure_sharedconst() const shared pure { return 0; }
1882 static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system"));
1883 static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system"));
1884 static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref"));
1886 static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system"));
1887 static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system"));
1888 static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc"));
1890 static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe"));
1891 static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe"));
1892 static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1894 auto safeDel = delegate() @safe { };
1895 static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe"));
1896 static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe"));
1897 static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system"));
1899 auto trustedDel = delegate() @trusted { };
1900 static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted"));
1901 static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted"));
1902 static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1904 auto systemDel = delegate() @system { };
1905 static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system"));
1906 static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system"));
1907 static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property"));
1910 // call functions to make CodeCov happy
1912 assert(pure_nothrow == 0);
1913 safe_nothrow;
1914 assert(static_ref_property == 0);
1915 assert(ref_property == 0);
1916 assert(S2().pure_const == 0);
1917 assert((shared S2()).pure_sharedconst == 0);
1918 cast(void) safeDel;
1919 cast(void) trustedDel;
1920 cast(void) systemDel;
1925 `true` if `func` is `@safe` or `@trusted`.
1927 template isSafe(alias func)
1928 if (isCallable!func)
1930 enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 ||
1931 (functionAttributes!func & FunctionAttribute.trusted) != 0;
1935 @safe unittest
1937 @safe int add(int a, int b) {return a+b;}
1938 @trusted int sub(int a, int b) {return a-b;}
1939 @system int mul(int a, int b) {return a*b;}
1941 static assert( isSafe!add);
1942 static assert( isSafe!sub);
1943 static assert(!isSafe!mul);
1947 @safe unittest
1949 //Member functions
1950 interface Set
1952 int systemF() @system;
1953 int trustedF() @trusted;
1954 int safeF() @safe;
1956 static assert( isSafe!(Set.safeF));
1957 static assert( isSafe!(Set.trustedF));
1958 static assert(!isSafe!(Set.systemF));
1960 //Functions
1961 @safe static void safeFunc() {}
1962 @trusted static void trustedFunc() {}
1963 @system static void systemFunc() {}
1965 static assert( isSafe!safeFunc);
1966 static assert( isSafe!trustedFunc);
1967 static assert(!isSafe!systemFunc);
1969 //Delegates
1970 auto safeDel = delegate() @safe {};
1971 auto trustedDel = delegate() @trusted {};
1972 auto systemDel = delegate() @system {};
1974 static assert( isSafe!safeDel);
1975 static assert( isSafe!trustedDel);
1976 static assert(!isSafe!systemDel);
1978 //Lambdas
1979 static assert( isSafe!({safeDel();}));
1980 static assert( isSafe!({trustedDel();}));
1981 static assert(!isSafe!({systemDel();}));
1983 //Static opCall
1984 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
1985 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
1986 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
1988 static assert( isSafe!(SafeStatic()));
1989 static assert( isSafe!(TrustedStatic()));
1990 static assert(!isSafe!(SystemStatic()));
1992 //Non-static opCall
1993 struct Safe { @safe Safe opCall() { return Safe.init; } }
1994 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
1995 struct System { @system System opCall() { return System.init; } }
1997 static assert( isSafe!(Safe.init()));
1998 static assert( isSafe!(Trusted.init()));
1999 static assert(!isSafe!(System.init()));
2004 `true` if `func` is `@system`.
2006 template isUnsafe(alias func)
2008 enum isUnsafe = !isSafe!func;
2012 @safe unittest
2014 @safe int add(int a, int b) {return a+b;}
2015 @trusted int sub(int a, int b) {return a-b;}
2016 @system int mul(int a, int b) {return a*b;}
2018 static assert(!isUnsafe!add);
2019 static assert(!isUnsafe!sub);
2020 static assert( isUnsafe!mul);
2023 @safe unittest
2025 //Member functions
2026 interface Set
2028 int systemF() @system;
2029 int trustedF() @trusted;
2030 int safeF() @safe;
2032 static assert(!isUnsafe!(Set.safeF));
2033 static assert(!isUnsafe!(Set.trustedF));
2034 static assert( isUnsafe!(Set.systemF));
2036 //Functions
2037 @safe static void safeFunc() {}
2038 @trusted static void trustedFunc() {}
2039 @system static void systemFunc() {}
2041 static assert(!isUnsafe!safeFunc);
2042 static assert(!isUnsafe!trustedFunc);
2043 static assert( isUnsafe!systemFunc);
2045 //Delegates
2046 auto safeDel = delegate() @safe {};
2047 auto trustedDel = delegate() @trusted {};
2048 auto systemDel = delegate() @system {};
2050 static assert(!isUnsafe!safeDel);
2051 static assert(!isUnsafe!trustedDel);
2052 static assert( isUnsafe!systemDel);
2054 //Lambdas
2055 static assert(!isUnsafe!({safeDel();}));
2056 static assert(!isUnsafe!({trustedDel();}));
2057 static assert( isUnsafe!({systemDel();}));
2059 //Static opCall
2060 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
2061 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
2062 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
2064 static assert(!isUnsafe!(SafeStatic()));
2065 static assert(!isUnsafe!(TrustedStatic()));
2066 static assert( isUnsafe!(SystemStatic()));
2068 //Non-static opCall
2069 struct Safe { @safe Safe opCall() { return Safe.init; } }
2070 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
2071 struct System { @system System opCall() { return System.init; } }
2073 static assert(!isUnsafe!(Safe.init()));
2074 static assert(!isUnsafe!(Trusted.init()));
2075 static assert( isUnsafe!(System.init()));
2080 Determine the linkage attribute of the function.
2081 Params:
2082 func = the function symbol, or the type of a function, delegate, or pointer to function
2083 Returns:
2084 one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
2086 template functionLinkage(alias func)
2087 if (isCallable!func)
2089 enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
2093 @safe unittest
2095 extern(D) void Dfunc() {}
2096 extern(C) void Cfunc() {}
2097 static assert(functionLinkage!Dfunc == "D");
2098 static assert(functionLinkage!Cfunc == "C");
2100 string a = functionLinkage!Dfunc;
2101 assert(a == "D");
2103 auto fp = &Cfunc;
2104 string b = functionLinkage!fp;
2105 assert(b == "C");
2108 @safe unittest
2110 interface Test
2112 void const_func() const;
2113 void sharedconst_func() shared const;
2115 static assert(functionLinkage!(Test.const_func) == "D");
2116 static assert(functionLinkage!(Test.sharedconst_func) == "D");
2118 static assert(functionLinkage!((int a){}) == "D");
2123 Determines what kind of variadic parameters function has.
2124 Params:
2125 func = function symbol or type of function, delegate, or pointer to function
2126 Returns:
2127 enum Variadic
2129 enum Variadic
2131 /// Function is not variadic.
2133 /// Function is a _C-style variadic function, which uses
2134 /// `core.stdc.stdarg`
2136 /// Function is a _D-style variadic function, which uses
2137 /// `__argptr` and `__arguments`.
2139 /// Function is a typesafe variadic function.
2140 typesafe,
2143 /// ditto
2144 template variadicFunctionStyle(alias func)
2145 if (isCallable!func)
2147 enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
2148 enum Variadic variadicFunctionStyle =
2149 (varargs == "stdarg") ? Variadic.c :
2150 (varargs == "argptr") ? Variadic.d :
2151 (varargs == "typesafe") ? Variadic.typesafe :
2152 (varargs == "none") ? Variadic.no : Variadic.no;
2156 @safe unittest
2158 void func() {}
2159 static assert(variadicFunctionStyle!func == Variadic.no);
2161 extern(C) int printf(const char*, ...);
2162 static assert(variadicFunctionStyle!printf == Variadic.c);
2165 @safe unittest
2167 import core.vararg;
2169 extern(D) void novar() {}
2170 extern(C) void cstyle(int, ...) {}
2171 extern(D) void dstyle(...) {}
2172 extern(D) void typesafe(int[]...) {}
2174 static assert(variadicFunctionStyle!novar == Variadic.no);
2175 static assert(variadicFunctionStyle!cstyle == Variadic.c);
2176 static assert(variadicFunctionStyle!dstyle == Variadic.d);
2177 static assert(variadicFunctionStyle!typesafe == Variadic.typesafe);
2179 static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe);
2184 Get the function type from a callable object `func`, or from a function pointer/delegate type.
2186 Using builtin `typeof` on a property function yields the types of the
2187 property value, not of the property function itself. Still,
2188 `FunctionTypeOf` is able to obtain function types of properties.
2190 Note:
2191 Do not confuse function types with function pointer types; function types are
2192 usually used for compile-time reflection purposes.
2194 template FunctionTypeOf(alias func)
2195 if (isCallable!func)
2197 static if ((is(typeof(& func) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func) Fsym == delegate))
2199 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
2201 else static if (is(typeof(& func.opCall) Fobj == delegate) || is(typeof(& func.opCall!()) Fobj == delegate))
2203 alias FunctionTypeOf = Fobj; // HIT: callable object
2205 else static if (
2206 (is(typeof(& func.opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
2207 (is(typeof(& func.opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
2210 alias FunctionTypeOf = Ftyp; // HIT: callable type
2212 else static if (is(func T) || is(typeof(func) T))
2214 static if (is(T == function))
2215 alias FunctionTypeOf = T; // HIT: function
2216 else static if (is(T Fptr : Fptr*) && is(Fptr == function))
2217 alias FunctionTypeOf = Fptr; // HIT: function pointer
2218 else static if (is(T Fdlg == delegate))
2219 alias FunctionTypeOf = Fdlg; // HIT: delegate
2220 else
2221 static assert(0);
2223 else
2224 static assert(0);
2228 @safe unittest
2230 class C
2232 int value() @property => 0;
2233 static string opCall() => "hi";
2235 static assert(is( typeof(C.value) == int ));
2236 static assert(is( FunctionTypeOf!(C.value) == function ));
2237 static assert(is( FunctionTypeOf!C == typeof(C.opCall) ));
2239 int function() fp;
2240 alias IntFn = int();
2241 static assert(is( typeof(fp) == IntFn* ));
2242 static assert(is( FunctionTypeOf!fp == IntFn ));
2245 @system unittest
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 ));
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 ));
2266 class Callable { int opCall(int) { return 0; } }
2267 auto call = new Callable;
2268 static assert(is( FunctionTypeOf!call == typeof(test) ));
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) ));
2276 struct TemplatedOpCallF { int opCall()(int) { return 0; } }
2277 static assert(is( FunctionTypeOf!TemplatedOpCallF == typeof(TemplatedOpCallF.opCall!()) ));
2279 int foovar;
2280 struct TemplatedOpCallDg { int opCall()() { return foovar; } }
2281 static assert(is( FunctionTypeOf!TemplatedOpCallDg == typeof(TemplatedOpCallDg.opCall!()) ));
2283 interface Overloads
2285 void test(string);
2286 real test(real);
2287 int test(int);
2288 int test() @property;
2290 alias ov = __traits(getVirtualMethods, 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));
2300 alias F_dglit = FunctionTypeOf!((int a){ return a; });
2301 static assert(is(F_dglit* : int function(int)));
2305 * Constructs a new function or delegate type with the same basic signature
2306 * as the given one, but different attributes (including linkage).
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.
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.
2316 template SetFunctionAttributes(T, string linkage, uint attrs)
2317 if (isFunctionPointer!T || isDelegate!T)
2319 mixin({
2320 import std.algorithm.searching : canFind;
2322 static assert(!(attrs & FunctionAttribute.trusted) ||
2323 !(attrs & FunctionAttribute.safe),
2324 "Cannot have a function/delegate that is both trusted and safe.");
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 ~ ".");
2330 string result = "alias ";
2332 static if (linkage != "D")
2333 result ~= "extern(" ~ linkage ~ ") ";
2335 static if (attrs & FunctionAttribute.ref_)
2336 result ~= "ref ";
2338 result ~= "ReturnType!T";
2340 static if (isDelegate!T)
2341 result ~= " delegate";
2342 else
2343 result ~= " function";
2345 result ~= "(";
2347 static if (Parameters!T.length > 0)
2348 result ~= "Parameters!T";
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 ~= "...";
2358 result ~= ")";
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";
2387 result ~= " SetFunctionAttributes;";
2388 return result;
2389 }());
2392 /// Ditto
2393 template SetFunctionAttributes(T, string linkage, uint attrs)
2394 if (is(T == function))
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));
2403 @safe unittest
2405 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
2407 auto assumePure(T)(T t)
2408 if (isFunctionPointer!T || isDelegate!T)
2410 enum attrs = functionAttributes!T | FunctionAttribute.pure_;
2411 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
2414 int f()
2416 import core.thread : getpid;
2417 return getpid();
2420 int g() pure @trusted
2422 auto pureF = assumePure(&f);
2423 return pureF();
2425 assert(g() > 0);
2428 version (StdUnittest)
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[]...);
2438 @safe unittest
2440 import std.algorithm.iteration : reduce;
2442 alias FA = FunctionAttribute;
2443 static foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle),
2444 typeof(&dstyle), typeof(&typesafe)))
2446 static foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT))
2448 enum linkage = functionLinkage!T;
2449 enum attrs = functionAttributes!T;
2451 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T),
2452 "Identity check failed for: " ~ T.stringof);
2454 // Check that all linkage types work (D-style variadics require D linkage).
2455 static if (variadicFunctionStyle!T != Variadic.d)
2457 static foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++"))
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 ~ ")");
2466 // Add @safe.
2467 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe);
2468 static assert(functionAttributes!T1 == FA.safe);
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_;
2475 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs);
2476 static assert(functionAttributes!T2 == allAttrs);
2478 // Strip all attributes again.
2479 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none);
2480 static assert(is(T3 == T));
2486 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2487 // Aggregate Types
2488 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
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)
2495 Params:
2496 T = type to test
2498 Returns:
2499 `true` if `T` is a class nested inside another, with the conditions described above;
2500 `false` otherwise
2502 template isInnerClass(T)
2503 if (is(T == class))
2505 static if (is(typeof(T.outer)))
2507 bool hasOuterMember(string[] members...)
2509 foreach (m; members)
2511 if (m == "outer")
2512 return true;
2514 return false;
2516 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) &&
2517 !hasOuterMember(__traits(allMembers, T));
2519 else
2520 enum isInnerClass = false;
2524 @safe unittest
2526 class C
2528 int outer;
2530 static assert(!isInnerClass!C);
2532 class Outer1
2534 class Inner1 { }
2535 class Inner2
2537 int outer;
2540 static assert(isInnerClass!(Outer1.Inner1));
2541 static assert(!isInnerClass!(Outer1.Inner2));
2543 static class Outer2
2545 static class Inner
2547 int outer;
2550 static assert(!isInnerClass!(Outer2.Inner));
2554 Determines whether `T` has its own context pointer.
2555 `T` must be either `class`, `struct`, or `union`.
2557 See also: $(DDSUBLINK spec/traits, isNested, `__traits(isNested, T)`)
2559 template isNested(T)
2560 if (is(T == class) || is(T == struct) || is(T == union))
2562 enum isNested = __traits(isNested, T);
2566 @safe unittest
2568 static struct S { }
2569 static assert(!isNested!S);
2571 int i;
2572 struct NestedStruct { void f() { ++i; } }
2573 static assert(isNested!NestedStruct);
2577 Determines whether `T` or any of its representation types
2578 have a context pointer.
2580 template hasNested(T)
2582 import std.meta : Filter;
2584 static if (isStaticArray!T && T.length)
2585 enum hasNested = hasNested!(typeof(T.init[0]));
2586 else static if (is(T == class) || is(T == struct) || is(T == union))
2588 // prevent infinite recursion for class with member of same type
2589 enum notSame(U) = !is(immutable T == immutable U);
2590 enum hasNested = isNested!T ||
2591 anySatisfy!(.hasNested, Filter!(notSame, Fields!T));
2593 else
2594 enum hasNested = false;
2598 @safe unittest
2600 static struct S { }
2602 int i;
2603 struct NS { void f() { ++i; } }
2605 static assert(!hasNested!(S[2]));
2606 static assert(hasNested!(NS[2]));
2609 @safe unittest
2611 static assert(!__traits(compiles, isNested!int));
2612 static assert(!hasNested!int);
2614 static struct StaticStruct { }
2615 static assert(!isNested!StaticStruct);
2616 static assert(!hasNested!StaticStruct);
2618 int i;
2619 struct NestedStruct { void f() { ++i; } }
2620 static assert( isNested!NestedStruct);
2621 static assert( hasNested!NestedStruct);
2622 static assert( isNested!(immutable NestedStruct));
2623 static assert( hasNested!(immutable NestedStruct));
2625 static assert(!__traits(compiles, isNested!(NestedStruct[1])));
2626 static assert( hasNested!(NestedStruct[1]));
2627 static assert(!hasNested!(NestedStruct[0]));
2629 struct S1 { NestedStruct nested; }
2630 static assert(!isNested!S1);
2631 static assert( hasNested!S1);
2633 static struct S2 { NestedStruct nested; }
2634 static assert(!isNested!S2);
2635 static assert( hasNested!S2);
2637 static struct S3 { NestedStruct[0] nested; }
2638 static assert(!isNested!S3);
2639 static assert(!hasNested!S3);
2641 static union U { NestedStruct nested; }
2642 static assert(!isNested!U);
2643 static assert( hasNested!U);
2645 static class StaticClass { }
2646 static assert(!isNested!StaticClass);
2647 static assert(!hasNested!StaticClass);
2649 class NestedClass { void f() { ++i; } }
2650 static assert( isNested!NestedClass);
2651 static assert( hasNested!NestedClass);
2652 static assert( isNested!(immutable NestedClass));
2653 static assert( hasNested!(immutable NestedClass));
2655 static assert(!__traits(compiles, isNested!(NestedClass[1])));
2656 static assert( hasNested!(NestedClass[1]));
2657 static assert(!hasNested!(NestedClass[0]));
2659 static class A
2661 A a;
2663 static assert(!hasNested!A);
2667 /***
2668 * Get as a tuple the types of the fields of a struct, class, or union.
2669 * This consists of the fields that take up memory space,
2670 * excluding the hidden fields like the virtual function
2671 * table pointer or a context pointer for nested types.
2672 * If `T` isn't a struct, class, interface or union returns a tuple
2673 * with one element `T`.
2675 * History:
2676 * - Returned `AliasSeq!(Interface)` for interfaces prior to 2.097
2678 template Fields(T)
2680 import core.internal.traits : _Fields = Fields;
2681 alias Fields = _Fields!T;
2685 @safe unittest
2687 import std.meta : AliasSeq;
2688 struct S { int x; float y; }
2689 static assert(is(Fields!S == AliasSeq!(int, float)));
2693 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2695 alias FieldTypeTuple = Fields;
2697 @safe unittest
2699 static assert(is(FieldTypeTuple!int == AliasSeq!int));
2701 static struct StaticStruct1 { }
2702 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!()));
2704 static struct StaticStruct2 { int a, b; }
2705 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int)));
2707 int i;
2709 struct NestedStruct1 { void f() { ++i; } }
2710 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!()));
2712 struct NestedStruct2 { int a; void f() { ++i; } }
2713 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int));
2715 class NestedClass { int a; void f() { ++i; } }
2716 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int));
2718 static interface I {}
2719 static assert(is(Fields!I == AliasSeq!()));
2722 //Required for FieldNameTuple
2723 private enum NameOf(alias T) = T.stringof;
2726 * Get as an expression tuple the names of the fields of a struct, class, or
2727 * union. This consists of the fields that take up memory space, excluding the
2728 * hidden fields like the virtual function table pointer or a context pointer
2729 * for nested types.
2730 * Inherited fields (for classes) are not included.
2731 * If `T` isn't a struct, class, interface or union, an
2732 * expression tuple with an empty string is returned.
2734 * History:
2735 * - Returned `AliasSeq!""` for interfaces prior to 2.097
2737 template FieldNameTuple(T)
2739 import std.meta : staticMap;
2740 static if (is(T == struct) || is(T == union))
2741 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]);
2742 else static if (is(T == class) || is(T == interface))
2743 alias FieldNameTuple = staticMap!(NameOf, T.tupleof);
2744 else
2745 alias FieldNameTuple = AliasSeq!"";
2749 @safe unittest
2751 import std.meta : AliasSeq;
2752 struct S { int x; float y; }
2753 static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
2754 static assert(FieldNameTuple!int == AliasSeq!"");
2757 @safe unittest
2759 static assert(FieldNameTuple!int == AliasSeq!"");
2761 static struct StaticStruct1 { }
2762 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!()));
2764 static struct StaticStruct2 { int a, b; }
2765 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b"));
2767 static class StaticClass1 { }
2768 static assert(is(FieldNameTuple!StaticClass1 == AliasSeq!()));
2770 static class StaticClass2 : StaticClass1 { int a, b; }
2771 static assert(FieldNameTuple!StaticClass2 == AliasSeq!("a", "b"));
2773 static class StaticClass3 : StaticClass2 { int c; }
2774 static assert(FieldNameTuple!StaticClass3 == AliasSeq!("c"));
2776 int i;
2778 struct NestedStruct1 { void f() { ++i; } }
2779 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!()));
2781 struct NestedStruct2 { int a; void f() { ++i; } }
2782 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a");
2784 class NestedClass { int a; void f() { ++i; } }
2785 static assert(FieldNameTuple!NestedClass == AliasSeq!"a");
2787 interface I {}
2788 static assert(FieldNameTuple!I == AliasSeq!());
2792 /***
2793 Get the primitive types of the fields of a struct or class, in
2794 topological order.
2796 template RepresentationTypeTuple(T)
2798 static if (is(T == struct) || is(T == union) || is(T == class))
2800 alias RepresentationTypeTuple = staticMapMeta!(RepresentationTypeTupleImpl, FieldTypeTuple!T);
2802 else
2804 alias RepresentationTypeTuple = RepresentationTypeTupleImpl!T;
2809 @safe unittest
2811 struct S1 { int a; float b; }
2812 struct S2 { char[] a; union { S1 b; S1 * c; } }
2813 alias R = RepresentationTypeTuple!S2;
2814 assert(R.length == 4
2815 && is(R[0] == char[]) && is(R[1] == int)
2816 && is(R[2] == float) && is(R[3] == S1*));
2819 @safe unittest
2821 alias S1 = RepresentationTypeTuple!int;
2822 static assert(is(S1 == AliasSeq!int));
2824 struct S2 { int a; }
2825 struct S3 { int a; char b; }
2826 struct S4 { S1 a; int b; S3 c; }
2827 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int));
2828 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char)));
2829 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char)));
2831 struct S11 { int a; float b; }
2832 struct S21 { char[] a; union { S11 b; S11 * c; } }
2833 alias R = RepresentationTypeTuple!S21;
2834 assert(R.length == 4
2835 && is(R[0] == char[]) && is(R[1] == int)
2836 && is(R[2] == float) && is(R[3] == S11*));
2838 class C { int a; float b; }
2839 alias R1 = RepresentationTypeTuple!C;
2840 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float));
2842 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
2843 import std.typecons : Rebindable;
2845 struct S5 { int a; Rebindable!(immutable Object) b; }
2846 alias R2 = RepresentationTypeTuple!S5;
2847 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
2849 static assert(is(RepresentationTypeTuple!noreturn == AliasSeq!noreturn));
2852 @safe unittest
2854 struct VeryLargeType
2856 import std.format : format;
2857 import std.range : iota;
2859 static foreach (i; 500.iota)
2861 mixin(format!"int v%s;"(i));
2865 alias BigList = RepresentationTypeTuple!VeryLargeType;
2868 private template RepresentationTypeTupleImpl(T)
2870 import std.typecons : Rebindable;
2872 static if (is(immutable T == immutable Rebindable!R, R))
2874 alias RepresentationTypeTupleImpl
2875 = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R);
2877 else static if (is(T == struct) || is(T == union))
2879 // @@@BUG@@@ this should work
2880 //alias .RepresentationTypes!(T[0].tupleof)
2881 // RepresentationTypes;
2882 alias RepresentationTypeTupleImpl
2883 = staticMapMeta!(.RepresentationTypeTupleImpl, FieldTypeTuple!(T));
2885 else
2887 alias RepresentationTypeTupleImpl
2888 = AliasSeq!T;
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.
2898 private template hasRawAliasing(T)
2900 enum hasRawAliasing = anySatisfy!(hasRawAliasingImpl, RepresentationTypeTuple!T);
2904 @safe unittest
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);
2921 // https://issues.dlang.org/show_bug.cgi?id=19228
2922 @safe unittest
2924 static struct C
2926 int*[1] a;
2928 static assert(hasRawAliasing!C);
2931 @safe unittest
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);
2944 union S6 { int a; int b; }
2945 union S7 { int a; int * b; }
2946 static assert(!hasRawAliasing!S6);
2947 static assert( hasRawAliasing!S7);
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())));
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);
2964 enum S9 { a }
2965 static assert(!hasRawAliasing!S9);
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);
2973 static assert( hasRawAliasing!(int[string]));
2974 static assert(!hasRawAliasing!(immutable(int[string])));
2977 private template hasRawAliasingImpl(T)
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;
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.
3001 private template hasRawUnsharedAliasing(T)
3003 enum hasRawUnsharedAliasing = anySatisfy!(hasRawUnsharedAliasingImpl, RepresentationTypeTuple!T);
3007 @safe unittest
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);
3031 @safe unittest
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);
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);
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()));
3082 enum S13 { a }
3083 static assert(!hasRawUnsharedAliasing!S13);
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);
3093 static assert( hasRawUnsharedAliasing!(int[string]));
3094 static assert(!hasRawUnsharedAliasing!(shared(int[string])));
3095 static assert(!hasRawUnsharedAliasing!(immutable(int[string])));
3097 struct S17
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;
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);
3156 private template hasRawUnsharedAliasingImpl(T)
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;
3169 Statically evaluates to `true` if and only if `T`'s
3170 representation includes at least one non-immutable object reference.
3173 private template hasObjects(T)
3175 static if (is(T == struct))
3177 enum hasObjects = anySatisfy!(.hasObjects, RepresentationTypeTuple!T);
3179 else
3181 enum hasObjects = (is(T == class) || is(T == interface)) && !is(T == immutable);
3186 Statically evaluates to `true` if and only if `T`'s
3187 representation includes at least one non-immutable non-shared object
3188 reference.
3190 private template hasUnsharedObjects(T)
3192 static if (is(T == struct))
3194 enum hasUnsharedObjects = anySatisfy!(.hasUnsharedObjects, RepresentationTypeTuple!T);
3196 else
3198 enum hasUnsharedObjects = (is(T == class) || is(T == interface)) &&
3199 !is(T == immutable) && !is(T == shared);
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.))
3211 template hasAliasing(T...)
3213 enum hasAliasing = anySatisfy!(hasAliasingImpl, T);
3217 @safe unittest
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);
3229 @safe unittest
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()));
3255 interface I;
3256 static assert( hasAliasing!I);
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));
3264 struct S5
3266 void delegate() immutable b;
3267 shared(void delegate() immutable) f;
3268 immutable(void delegate() immutable) j;
3269 shared(const(void delegate() immutable)) n;
3271 struct S6 { typeof(S5.tupleof) a; void delegate() p; }
3272 static assert(!hasAliasing!S5);
3273 static assert( hasAliasing!S6);
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);
3292 class S15 { S15[1] a; }
3293 static assert( hasAliasing!S15);
3294 static assert(!hasAliasing!(immutable(S15)));
3296 static assert(!hasAliasing!noreturn);
3299 private template hasAliasingImpl(T)
3301 import std.typecons : Rebindable;
3303 static if (is(immutable T == immutable Rebindable!R, R))
3305 enum hasAliasingImpl = hasAliasingImpl!R;
3307 else
3309 template isAliasingDelegate(T)
3311 enum isAliasingDelegate = isDelegate!T
3312 && !is(T == immutable)
3313 && !is(FunctionTypeOf!T == immutable);
3315 enum hasAliasingImpl = hasRawAliasing!T || hasObjects!T ||
3316 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T);
3321 Returns `true` if and only if `T`'s representation includes at
3322 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an
3323 array `U[]`;) $(LI a reference to a class type `C`;)
3324 $(LI an associative array;) $(LI a delegate;)
3325 $(LI a [context pointer][isNested].))
3327 template hasIndirections(T)
3329 import core.internal.traits : _hasIndirections = hasIndirections;
3330 alias hasIndirections = _hasIndirections!T;
3334 @safe unittest
3336 static assert( hasIndirections!(int[string]));
3337 static assert( hasIndirections!(void delegate()));
3338 static assert( hasIndirections!(void delegate() immutable));
3339 static assert( hasIndirections!(immutable(void delegate())));
3340 static assert( hasIndirections!(immutable(void delegate() immutable)));
3342 static assert(!hasIndirections!(void function()));
3343 static assert( hasIndirections!(void*[1]));
3344 static assert(!hasIndirections!(byte[1]));
3347 @safe unittest
3349 // void static array hides actual type of bits, so "may have indirections".
3350 static assert( hasIndirections!(void[1]));
3351 interface I {}
3352 struct S1 {}
3353 struct S2 { int a; }
3354 struct S3 { int a; int b; }
3355 struct S4 { int a; int* b; }
3356 struct S5 { int a; Object b; }
3357 struct S6 { int a; string b; }
3358 struct S7 { int a; immutable Object b; }
3359 struct S8 { int a; immutable I b; }
3360 struct S9 { int a; void delegate() b; }
3361 struct S10 { int a; immutable(void delegate()) b; }
3362 struct S11 { int a; void delegate() immutable b; }
3363 struct S12 { int a; immutable(void delegate() immutable) b; }
3364 class S13 {}
3365 class S14 { int a; }
3366 class S15 { int a; int b; }
3367 class S16 { int a; Object b; }
3368 class S17 { string a; }
3369 class S18 { int a; immutable Object b; }
3370 class S19 { int a; immutable(void delegate() immutable) b; }
3371 union S20 {}
3372 union S21 { int a; }
3373 union S22 { int a; int b; }
3374 union S23 { int a; Object b; }
3375 union S24 { string a; }
3376 union S25 { int a; immutable Object b; }
3377 union S26 { int a; immutable(void delegate() immutable) b; }
3378 static assert( hasIndirections!I);
3379 static assert(!hasIndirections!S1);
3380 static assert(!hasIndirections!S2);
3381 static assert(!hasIndirections!S3);
3382 static assert( hasIndirections!S4);
3383 static assert( hasIndirections!S5);
3384 static assert( hasIndirections!S6);
3385 static assert( hasIndirections!S7);
3386 static assert( hasIndirections!S8);
3387 static assert( hasIndirections!S9);
3388 static assert( hasIndirections!S10);
3389 static assert( hasIndirections!S12);
3390 static assert( hasIndirections!S13);
3391 static assert( hasIndirections!S14);
3392 static assert( hasIndirections!S15);
3393 static assert( hasIndirections!S16);
3394 static assert( hasIndirections!S17);
3395 static assert( hasIndirections!S18);
3396 static assert( hasIndirections!S19);
3397 static assert(!hasIndirections!S20);
3398 static assert(!hasIndirections!S21);
3399 static assert(!hasIndirections!S22);
3400 static assert( hasIndirections!S23);
3401 static assert( hasIndirections!S24);
3402 static assert( hasIndirections!S25);
3403 static assert( hasIndirections!S26);
3404 int local;
3405 struct HasContextPointer { int opCall() { return ++local; } }
3406 static assert(hasIndirections!HasContextPointer);
3408 static assert(!hasIndirections!noreturn);
3411 // https://issues.dlang.org/show_bug.cgi?id=12000
3412 @safe unittest
3414 static struct S(T)
3416 static assert(hasIndirections!T);
3419 static class A(T)
3421 S!A a;
3424 A!int dummy;
3428 Returns `true` if and only if `T`'s representation includes at
3429 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3430 is not immutable or shared;) $(LI an array `U[]` and `U` is not
3431 immutable or shared;) $(LI a reference to a class type `C` and
3432 `C` is not immutable or shared.) $(LI an associative array that is not
3433 immutable or shared.) $(LI a delegate that is not shared.))
3436 template hasUnsharedAliasing(T...)
3438 enum hasUnsharedAliasing = anySatisfy!(hasUnsharedAliasingImpl, T);
3442 @safe unittest
3444 struct S1 { int a; Object b; }
3445 struct S2 { string a; }
3446 struct S3 { int a; immutable Object b; }
3447 static assert( hasUnsharedAliasing!S1);
3448 static assert(!hasUnsharedAliasing!S2);
3449 static assert(!hasUnsharedAliasing!S3);
3451 struct S4 { int a; shared Object b; }
3452 struct S5 { char[] a; }
3453 struct S6 { shared char[] b; }
3454 struct S7 { float[3] vals; }
3455 static assert(!hasUnsharedAliasing!S4);
3456 static assert( hasUnsharedAliasing!S5);
3457 static assert(!hasUnsharedAliasing!S6);
3458 static assert(!hasUnsharedAliasing!S7);
3461 @safe unittest
3463 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
3464 import std.typecons : Rebindable;
3465 struct S8 { int a; Rebindable!(immutable Object) b; }
3466 static assert(!hasUnsharedAliasing!S8);
3468 static assert( hasUnsharedAliasing!(uint[uint]));
3470 static assert( hasUnsharedAliasing!(void delegate()));
3471 static assert( hasUnsharedAliasing!(void delegate() const));
3472 static assert(!hasUnsharedAliasing!(void delegate() immutable));
3473 static assert(!hasUnsharedAliasing!(void delegate() shared));
3474 static assert(!hasUnsharedAliasing!(void delegate() shared const));
3477 @safe unittest
3479 import std.typecons : Rebindable;
3480 static assert( hasUnsharedAliasing!(const(void delegate())));
3481 static assert( hasUnsharedAliasing!(const(void delegate() const)));
3482 static assert(!hasUnsharedAliasing!(const(void delegate() immutable)));
3483 static assert(!hasUnsharedAliasing!(const(void delegate() shared)));
3484 static assert(!hasUnsharedAliasing!(const(void delegate() shared const)));
3485 static assert(!hasUnsharedAliasing!(immutable(void delegate())));
3486 static assert(!hasUnsharedAliasing!(immutable(void delegate() const)));
3487 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable)));
3488 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared)));
3489 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const)));
3490 static assert(!hasUnsharedAliasing!(shared(void delegate())));
3491 static assert(!hasUnsharedAliasing!(shared(void delegate() const)));
3492 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable)));
3493 static assert(!hasUnsharedAliasing!(shared(void delegate() shared)));
3494 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const)));
3495 static assert(!hasUnsharedAliasing!(shared(const(void delegate()))));
3496 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const))));
3497 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable))));
3498 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared))));
3499 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const))));
3500 static assert(!hasUnsharedAliasing!(void function()));
3502 interface I {}
3503 static assert(hasUnsharedAliasing!I);
3505 static assert( hasUnsharedAliasing!(Rebindable!(const Object)));
3506 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object)));
3507 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object)));
3508 static assert( hasUnsharedAliasing!(Rebindable!Object));
3510 /* https://issues.dlang.org/show_bug.cgi?id=6979 */
3511 static assert(!hasUnsharedAliasing!(int, shared(int)*));
3512 static assert( hasUnsharedAliasing!(int, int*));
3513 static assert( hasUnsharedAliasing!(int, const(int)[]));
3514 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object));
3515 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object)));
3516 static assert(!hasUnsharedAliasing!());
3518 struct S9
3520 void delegate() shared a;
3521 void delegate() immutable b;
3522 void delegate() shared const c;
3523 shared(void delegate()) d;
3524 shared(void delegate() shared) e;
3525 shared(void delegate() immutable) f;
3526 shared(void delegate() shared const) g;
3527 immutable(void delegate()) h;
3528 immutable(void delegate() shared) i;
3529 immutable(void delegate() immutable) j;
3530 immutable(void delegate() shared const) k;
3531 shared(const(void delegate())) l;
3532 shared(const(void delegate() shared)) m;
3533 shared(const(void delegate() immutable)) n;
3534 shared(const(void delegate() shared const)) o;
3536 struct S10 { typeof(S9.tupleof) a; void delegate() p; }
3537 struct S11 { typeof(S9.tupleof) a; Object p; }
3538 struct S12 { typeof(S9.tupleof) a; int* p; }
3539 class S13 { typeof(S9.tupleof) a; }
3540 class S14 { typeof(S9.tupleof) a; void delegate() p; }
3541 class S15 { typeof(S9.tupleof) a; Object p; }
3542 class S16 { typeof(S9.tupleof) a; int* p; }
3543 static assert(!hasUnsharedAliasing!S9);
3544 static assert(!hasUnsharedAliasing!(immutable(S9)));
3545 static assert(!hasUnsharedAliasing!(shared(S9)));
3546 static assert( hasUnsharedAliasing!S10);
3547 static assert(!hasUnsharedAliasing!(immutable(S10)));
3548 static assert(!hasUnsharedAliasing!(shared(S10)));
3549 static assert( hasUnsharedAliasing!S11);
3550 static assert(!hasUnsharedAliasing!(immutable(S11)));
3551 static assert(!hasUnsharedAliasing!(shared(S11)));
3552 static assert( hasUnsharedAliasing!S12);
3553 static assert(!hasUnsharedAliasing!(immutable(S12)));
3554 static assert(!hasUnsharedAliasing!(shared(S12)));
3555 static assert( hasUnsharedAliasing!S13);
3556 static assert(!hasUnsharedAliasing!(immutable(S13)));
3557 static assert(!hasUnsharedAliasing!(shared(S13)));
3558 static assert( hasUnsharedAliasing!S14);
3559 static assert(!hasUnsharedAliasing!(immutable(S14)));
3560 static assert(!hasUnsharedAliasing!(shared(S14)));
3561 static assert( hasUnsharedAliasing!S15);
3562 static assert(!hasUnsharedAliasing!(immutable(S15)));
3563 static assert(!hasUnsharedAliasing!(shared(S15)));
3564 static assert( hasUnsharedAliasing!S16);
3565 static assert(!hasUnsharedAliasing!(immutable(S16)));
3566 static assert(!hasUnsharedAliasing!(shared(S16)));
3567 struct S17 {}
3568 class S18 {}
3569 interface S19 {}
3570 union S20 {}
3571 static assert(!hasUnsharedAliasing!S17);
3572 static assert( hasUnsharedAliasing!S18);
3573 static assert( hasUnsharedAliasing!S19);
3574 static assert(!hasUnsharedAliasing!S20);
3576 static assert(!hasUnsharedAliasing!noreturn);
3579 private template hasUnsharedAliasingImpl(T)
3581 import std.typecons : Rebindable;
3583 static if (is(immutable T == immutable Rebindable!R, R))
3585 enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R;
3587 else
3589 template unsharedDelegate(T)
3591 enum bool unsharedDelegate = isDelegate!T
3592 && !is(T == shared)
3593 && !is(T == immutable)
3594 && !is(FunctionTypeOf!T == shared)
3595 && !is(FunctionTypeOf!T == immutable);
3598 enum hasUnsharedAliasingImpl =
3599 hasRawUnsharedAliasing!T ||
3600 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!T) ||
3601 hasUnsharedObjects!T;
3605 version (StdDdoc)
3608 True if `S` or any type embedded directly in the representation of `S`
3609 defines an elaborate copy constructor. Elaborate copy constructors are
3610 introduced by defining `this(this)` for a `struct`.
3612 Classes and unions never have elaborate copy constructors.
3614 template hasElaborateCopyConstructor(S)
3616 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3617 alias hasElaborateCopyConstructor = hasElabCCtor!(S);
3620 else
3622 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3623 alias hasElaborateCopyConstructor = hasElabCCtor;
3627 @safe unittest
3629 static assert(!hasElaborateCopyConstructor!int);
3631 static struct S1 { }
3632 static struct S2 { this(this) {} }
3633 static struct S3 { S2 field; }
3634 static struct S4 { S3[1] field; }
3635 static struct S5 { S3[] field; }
3636 static struct S6 { S3[0] field; }
3637 static struct S7 { @disable this(); S3 field; }
3638 static assert(!hasElaborateCopyConstructor!S1);
3639 static assert( hasElaborateCopyConstructor!S2);
3640 static assert( hasElaborateCopyConstructor!(immutable S2));
3641 static assert( hasElaborateCopyConstructor!S3);
3642 static assert( hasElaborateCopyConstructor!(S3[1]));
3643 static assert(!hasElaborateCopyConstructor!(S3[0]));
3644 static assert( hasElaborateCopyConstructor!S4);
3645 static assert(!hasElaborateCopyConstructor!S5);
3646 static assert(!hasElaborateCopyConstructor!S6);
3647 static assert( hasElaborateCopyConstructor!S7);
3651 True if `S` or any type directly embedded in the representation of `S`
3652 defines an elaborate assignment. Elaborate assignments are introduced by
3653 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this)))
3654 for a `struct` or when there is a compiler-generated `opAssign`.
3656 A type `S` gets compiler-generated `opAssign` if it has
3657 an elaborate destructor.
3659 Classes and unions never have elaborate assignments.
3661 Note: Structs with (possibly nested) postblit operator(s) will have a
3662 hidden yet elaborate compiler generated assignment operator (unless
3663 explicitly disabled).
3665 template hasElaborateAssign(S)
3667 static if (isStaticArray!S && S.length)
3669 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0]));
3671 else static if (is(S == struct))
3673 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
3674 is(typeof(S.init.opAssign(lvalueOf!S))) ||
3675 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S);
3677 else
3679 enum bool hasElaborateAssign = false;
3684 @safe unittest
3686 static assert(!hasElaborateAssign!int);
3688 static struct S { void opAssign(S) {} }
3689 static assert( hasElaborateAssign!S);
3690 static assert(!hasElaborateAssign!(const(S)));
3692 static struct S1 { void opAssign(ref S1) {} }
3693 static struct S2 { void opAssign(int) {} }
3694 static struct S3 { S s; }
3695 static assert( hasElaborateAssign!S1);
3696 static assert(!hasElaborateAssign!S2);
3697 static assert( hasElaborateAssign!S3);
3698 static assert( hasElaborateAssign!(S3[1]));
3699 static assert(!hasElaborateAssign!(S3[0]));
3702 @safe unittest
3704 static struct S { void opAssign(S) {} }
3705 static struct S4
3707 void opAssign(U)(U u) {}
3708 @disable void opAssign(U)(ref U u);
3710 static assert( hasElaborateAssign!S4);
3712 static struct S41
3714 void opAssign(U)(ref U u) {}
3715 @disable void opAssign(U)(U u);
3717 static assert( hasElaborateAssign!S41);
3719 static struct S5 { @disable this(); this(int n){ s = S(); } S s; }
3720 static assert( hasElaborateAssign!S5);
3722 static struct S6 { this(this) {} }
3723 static struct S7 { this(this) {} @disable void opAssign(S7); }
3724 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} }
3725 static struct S9 { this(this) {} void opAssign(int) {} }
3726 static struct S10 { ~this() { } }
3727 static assert( hasElaborateAssign!S6);
3728 static assert(!hasElaborateAssign!S7);
3729 static assert(!hasElaborateAssign!S8);
3730 static assert( hasElaborateAssign!S9);
3731 static assert( hasElaborateAssign!S10);
3732 static struct SS6 { S6 s; }
3733 static struct SS7 { S7 s; }
3734 static struct SS8 { S8 s; }
3735 static struct SS9 { S9 s; }
3736 static assert( hasElaborateAssign!SS6);
3737 static assert(!hasElaborateAssign!SS7);
3738 static assert(!hasElaborateAssign!SS8);
3739 static assert( hasElaborateAssign!SS9);
3742 version (StdDdoc)
3745 True if `S` or any type directly embedded in the representation
3746 of `S` defines an elaborate destructor. Elaborate destructors
3747 are introduced by defining `~this()` for a $(D
3748 struct).
3750 Classes and unions never have elaborate destructors, even
3751 though classes may define `~this()`.
3753 template hasElaborateDestructor(S)
3755 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3756 alias hasElaborateDestructor = hasElabDest!(S);
3759 else
3761 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3762 alias hasElaborateDestructor = hasElabDest;
3766 @safe unittest
3768 static assert(!hasElaborateDestructor!int);
3770 static struct S1 { }
3771 static struct S2 { ~this() {} }
3772 static struct S3 { S2 field; }
3773 static struct S4 { S3[1] field; }
3774 static struct S5 { S3[] field; }
3775 static struct S6 { S3[0] field; }
3776 static struct S7 { @disable this(); S3 field; }
3777 static assert(!hasElaborateDestructor!S1);
3778 static assert( hasElaborateDestructor!S2);
3779 static assert( hasElaborateDestructor!(immutable S2));
3780 static assert( hasElaborateDestructor!S3);
3781 static assert( hasElaborateDestructor!(S3[1]));
3782 static assert(!hasElaborateDestructor!(S3[0]));
3783 static assert( hasElaborateDestructor!S4);
3784 static assert(!hasElaborateDestructor!S5);
3785 static assert(!hasElaborateDestructor!S6);
3786 static assert( hasElaborateDestructor!S7);
3789 version (StdDdoc)
3792 True if `S` or any type embedded directly in the representation of `S`
3793 defines elaborate move semantics. Elaborate move semantics are
3794 introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
3796 Classes and unions never have elaborate move semantics.
3798 template hasElaborateMove(S)
3800 import core.internal.traits : hasElabMove = hasElaborateMove;
3801 alias hasElaborateMove = hasElabMove!(S);
3804 else
3806 import core.internal.traits : hasElabMove = hasElaborateMove;
3807 alias hasElaborateMove = hasElabMove;
3811 @safe unittest
3813 static assert(!hasElaborateMove!int);
3815 static struct S1 { }
3816 static struct S2 { void opPostMove(ref S2) {} }
3817 static struct S3 { void opPostMove(inout ref S3) inout {} }
3818 static struct S4 { void opPostMove(const ref S4) {} }
3819 static struct S5 { void opPostMove(S5) {} }
3820 static struct S6 { void opPostMove(int) {} }
3821 static struct S7 { S3[1] field; }
3822 static struct S8 { S3[] field; }
3823 static struct S9 { S3[0] field; }
3824 static struct S10 { @disable this(); S3 field; }
3825 static assert(!hasElaborateMove!S1);
3826 static assert( hasElaborateMove!S2);
3827 static assert( hasElaborateMove!S3);
3828 static assert( hasElaborateMove!(immutable S3));
3829 static assert( hasElaborateMove!S4);
3830 static assert(!hasElaborateMove!S5);
3831 static assert(!hasElaborateMove!S6);
3832 static assert( hasElaborateMove!S7);
3833 static assert(!hasElaborateMove!S8);
3834 static assert(!hasElaborateMove!S9);
3835 static assert( hasElaborateMove!S10);
3838 package alias Identity(alias A) = A;
3841 Yields `true` if and only if `T` is an aggregate that defines
3842 a symbol called `name`.
3844 See also: $(DDSUBLINK spec/traits, hasMember, `__traits(hasMember, T, name)`)
3846 enum hasMember(T, string name) = __traits(hasMember, T, name);
3849 @safe unittest
3851 static assert(!hasMember!(int, "blah"));
3852 struct S1 { int blah; }
3853 struct S2 { int blah(){ return 0; } }
3854 class C1 { int blah; }
3855 class C2 { int blah(){ return 0; } }
3856 static assert(hasMember!(S1, "blah"));
3857 static assert(hasMember!(S2, "blah"));
3858 static assert(hasMember!(C1, "blah"));
3859 static assert(hasMember!(C2, "blah"));
3862 @safe unittest
3864 // https://issues.dlang.org/show_bug.cgi?id=8321
3865 struct S {
3866 int x;
3867 void f(){}
3868 void t()(){}
3869 template T(){}
3871 struct R1(T) {
3872 T t;
3873 alias t this;
3875 struct R2(T) {
3876 T t;
3877 @property ref inout(T) payload() inout { return t; }
3878 alias t this;
3880 static assert(hasMember!(S, "x"));
3881 static assert(hasMember!(S, "f"));
3882 static assert(hasMember!(S, "t"));
3883 static assert(hasMember!(S, "T"));
3884 static assert(hasMember!(R1!S, "x"));
3885 static assert(hasMember!(R1!S, "f"));
3886 static assert(hasMember!(R1!S, "t"));
3887 static assert(hasMember!(R1!S, "T"));
3888 static assert(hasMember!(R2!S, "x"));
3889 static assert(hasMember!(R2!S, "f"));
3890 static assert(hasMember!(R2!S, "t"));
3891 static assert(hasMember!(R2!S, "T"));
3894 @safe unittest
3896 static struct S
3898 void opDispatch(string n, A)(A dummy) {}
3900 static assert(hasMember!(S, "foo"));
3904 * Whether the symbol represented by the string, member, exists and is a static member of T.
3906 * Params:
3907 * T = Type containing symbol `member`.
3908 * member = Name of symbol to test that resides in `T`.
3910 * Returns:
3911 * `true` iff `member` exists and is static.
3913 template hasStaticMember(T, string member)
3915 static if (__traits(hasMember, T, member))
3917 static if (is(T == V*, V))
3918 alias U = V;
3919 else
3920 alias U = T;
3922 import std.meta : Alias;
3923 alias sym = Alias!(__traits(getMember, U, member));
3925 static if (__traits(getOverloads, U, member).length == 0)
3926 enum bool hasStaticMember = __traits(compiles, &sym);
3927 else
3928 enum bool hasStaticMember = __traits(isStaticFunction, sym);
3930 else
3932 enum bool hasStaticMember = false;
3937 @safe unittest
3939 static struct S
3941 static void sf() {}
3942 void f() {}
3944 static int si;
3945 int i;
3948 static assert( hasStaticMember!(S, "sf"));
3949 static assert(!hasStaticMember!(S, "f"));
3951 static assert( hasStaticMember!(S, "si"));
3952 static assert(!hasStaticMember!(S, "i"));
3954 static assert(!hasStaticMember!(S, "hello"));
3957 @safe unittest
3959 static struct S
3961 enum X = 10;
3962 enum Y
3964 i = 10
3966 struct S {}
3967 class C {}
3969 static int sx = 0;
3970 __gshared int gx = 0;
3972 Y y;
3973 static Y sy;
3975 static void f();
3976 static void f2() pure nothrow @nogc @safe;
3978 void g() shared;
3980 static void function() fp;
3981 __gshared void function() gfp;
3982 void function() fpm;
3984 void delegate() dm;
3985 static void delegate() sd;
3987 void m();
3988 void m2() const pure nothrow @nogc @safe;
3990 inout(int) iom() inout;
3991 static inout(int) iosf(inout int x);
3993 @property int p();
3994 static @property int sp();
3997 static class C
3999 enum X = 10;
4000 enum Y
4002 i = 10
4004 struct S {}
4005 class C {}
4007 static int sx = 0;
4008 __gshared int gx = 0;
4010 Y y;
4011 static Y sy;
4013 static void f();
4014 static void f2() pure nothrow @nogc @safe;
4016 void g() shared { }
4018 static void function() fp;
4019 __gshared void function() gfp;
4020 void function() fpm;
4022 void delegate() dm;
4023 static void delegate() sd;
4025 void m() {}
4026 final void m2() const pure nothrow @nogc @safe;
4028 inout(int) iom() inout { return 10; }
4029 static inout(int) iosf(inout int x);
4031 @property int p() { return 10; }
4032 static @property int sp();
4035 static assert(!hasStaticMember!(S, "na"));
4036 static assert(!hasStaticMember!(S, "X"));
4037 static assert(!hasStaticMember!(S, "Y"));
4038 static assert(!hasStaticMember!(S, "Y.i"));
4039 static assert(!hasStaticMember!(S, "S"));
4040 static assert(!hasStaticMember!(S, "C"));
4041 static assert( hasStaticMember!(S, "sx"));
4042 static assert( hasStaticMember!(S, "gx"));
4043 static assert(!hasStaticMember!(S, "y"));
4044 static assert( hasStaticMember!(S, "sy"));
4045 static assert( hasStaticMember!(S, "f"));
4046 static assert( hasStaticMember!(S, "f2"));
4047 static assert(!hasStaticMember!(S, "dm"));
4048 static assert( hasStaticMember!(S, "sd"));
4049 static assert(!hasStaticMember!(S, "g"));
4050 static assert( hasStaticMember!(S, "fp"));
4051 static assert( hasStaticMember!(S, "gfp"));
4052 static assert(!hasStaticMember!(S, "fpm"));
4053 static assert(!hasStaticMember!(S, "m"));
4054 static assert(!hasStaticMember!(S, "m2"));
4055 static assert(!hasStaticMember!(S, "iom"));
4056 static assert( hasStaticMember!(S, "iosf"));
4057 static assert(!hasStaticMember!(S, "p"));
4058 static assert( hasStaticMember!(S, "sp"));
4060 static assert(!hasStaticMember!(C, "na"));
4061 static assert(!hasStaticMember!(C, "X"));
4062 static assert(!hasStaticMember!(C, "Y"));
4063 static assert(!hasStaticMember!(C, "Y.i"));
4064 static assert(!hasStaticMember!(C, "S"));
4065 static assert(!hasStaticMember!(C, "C"));
4066 static assert( hasStaticMember!(C, "sx"));
4067 static assert( hasStaticMember!(C, "gx"));
4068 static assert(!hasStaticMember!(C, "y"));
4069 static assert( hasStaticMember!(C, "sy"));
4070 static assert( hasStaticMember!(C, "f"));
4071 static assert( hasStaticMember!(C, "f2"));
4072 static assert(!hasStaticMember!(C, "dm"));
4073 static assert( hasStaticMember!(C, "sd"));
4074 static assert(!hasStaticMember!(C, "g"));
4075 static assert( hasStaticMember!(C, "fp"));
4076 static assert( hasStaticMember!(C, "gfp"));
4077 static assert(!hasStaticMember!(C, "fpm"));
4078 static assert(!hasStaticMember!(C, "m"));
4079 static assert(!hasStaticMember!(C, "m2"));
4080 static assert(!hasStaticMember!(C, "iom"));
4081 static assert( hasStaticMember!(C, "iosf"));
4082 static assert(!hasStaticMember!(C, "p"));
4083 static assert( hasStaticMember!(C, "sp"));
4085 alias P = S*;
4086 static assert(!hasStaticMember!(P, "na"));
4087 static assert(!hasStaticMember!(P, "X"));
4088 static assert(!hasStaticMember!(P, "Y"));
4089 static assert(!hasStaticMember!(P, "Y.i"));
4090 static assert(!hasStaticMember!(P, "S"));
4091 static assert(!hasStaticMember!(P, "C"));
4092 static assert( hasStaticMember!(P, "sx"));
4093 static assert( hasStaticMember!(P, "gx"));
4094 static assert(!hasStaticMember!(P, "y"));
4095 static assert( hasStaticMember!(P, "sy"));
4096 static assert( hasStaticMember!(P, "f"));
4097 static assert( hasStaticMember!(P, "f2"));
4098 static assert(!hasStaticMember!(P, "dm"));
4099 static assert( hasStaticMember!(P, "sd"));
4100 static assert(!hasStaticMember!(P, "g"));
4101 static assert( hasStaticMember!(P, "fp"));
4102 static assert( hasStaticMember!(P, "gfp"));
4103 static assert(!hasStaticMember!(P, "fpm"));
4104 static assert(!hasStaticMember!(P, "m"));
4105 static assert(!hasStaticMember!(P, "m2"));
4106 static assert(!hasStaticMember!(P, "iom"));
4107 static assert( hasStaticMember!(P, "iosf"));
4108 static assert(!hasStaticMember!(P, "p"));
4109 static assert( hasStaticMember!(P, "sp"));
4113 Retrieves the members of an enumerated type `enum E`.
4115 Params:
4116 E = An enumerated type. `E` may have duplicated values.
4118 Returns:
4119 Static tuple composed of the members of the enumerated type `E`.
4120 The members are arranged in the same order as declared in `E`.
4121 The name of the enum can be found by querying the compiler for the
4122 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`.
4123 For enumerations with unique values, $(REF to, std,conv) can also be used.
4125 Note:
4126 An enum can have multiple members which have the same value. If you want
4127 to use EnumMembers to e.g. generate switch cases at compile-time,
4128 you should use the $(REF NoDuplicates, std,meta) template to avoid
4129 generating duplicate switch cases.
4131 Note:
4132 Returned values are strictly typed with `E`. Thus, the following code
4133 does not work without the explicit cast:
4134 --------------------
4135 enum E : int { a, b, c }
4136 int[] abc = cast(int[]) [ EnumMembers!E ];
4137 --------------------
4138 Cast is not necessary if the type of the variable is inferred. See the
4139 example below.
4141 template EnumMembers(E)
4142 if (is(E == enum))
4144 alias EnumMembers = AliasSeq!();
4145 static foreach (M; __traits(allMembers, E))
4146 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, M));
4149 /// Create an array of enumerated values
4150 @safe unittest
4152 enum Sqrts : real
4154 one = 1,
4155 two = 1.41421,
4156 three = 1.73205
4158 auto sqrts = [EnumMembers!Sqrts];
4159 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
4163 A generic function `rank(v)` in the following example uses this
4164 template for finding a member `e` in an enumerated type `E`.
4166 @safe unittest
4168 // Returns i if e is the i-th enumerator of E.
4169 static size_t rank(E)(E e)
4170 if (is(E == enum))
4172 static foreach (i, member; EnumMembers!E)
4174 if (e == member)
4175 return i;
4177 assert(0, "Not an enum member");
4180 enum Mode
4182 read = 1,
4183 write = 2,
4184 map = 4
4186 assert(rank(Mode.read) == 0);
4187 assert(rank(Mode.write) == 1);
4188 assert(rank(Mode.map) == 2);
4192 Use EnumMembers to generate a switch statement using static foreach.
4195 @safe unittest
4197 import std.conv : to;
4198 class FooClass
4200 string calledMethod;
4201 void foo() @safe { calledMethod = "foo"; }
4202 void bar() @safe { calledMethod = "bar"; }
4203 void baz() @safe { calledMethod = "baz"; }
4206 enum FooEnum { foo, bar, baz }
4208 auto var = FooEnum.bar;
4209 auto fooObj = new FooClass();
4210 s: final switch (var)
4212 static foreach (member; EnumMembers!FooEnum)
4214 case member: // Generate a case for each enum value.
4215 // Call fooObj.{name of enum value}().
4216 __traits(getMember, fooObj, to!string(member))();
4217 break s;
4220 // As we pass in FooEnum.bar, the bar() method gets called.
4221 assert(fooObj.calledMethod == "bar");
4224 @safe unittest
4226 enum A { a }
4227 static assert([ EnumMembers!A ] == [ A.a ]);
4228 enum B { a, b, c, d, e }
4229 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]);
4232 @safe unittest // typed enums
4234 enum A : string { a = "alpha", b = "beta" }
4235 static assert([ EnumMembers!A ] == [ A.a, A.b ]);
4237 static struct S
4239 int value;
4240 int opCmp(S rhs) const nothrow { return value - rhs.value; }
4242 enum B : S { a = S(1), b = S(2), c = S(3) }
4243 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]);
4246 @safe unittest // duplicated values
4248 enum A
4250 a = 0, b = 0,
4251 c = 1, d = 1, e
4253 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]);
4256 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
4257 @safe unittest
4259 string genEnum()
4261 string result = "enum TLAs {";
4262 foreach (c0; '0'..'2'+1)
4263 foreach (c1; '0'..'9'+1)
4264 foreach (c2; '0'..'9'+1)
4265 foreach (c3; '0'..'9'+1)
4267 result ~= '_';
4268 result ~= c0;
4269 result ~= c1;
4270 result ~= c2;
4271 result ~= c3;
4272 result ~= ',';
4274 result ~= '}';
4275 return result;
4277 mixin(genEnum);
4278 static assert(EnumMembers!TLAs[0] == TLAs._0000);
4279 static assert(EnumMembers!TLAs[$-1] == TLAs._2999);
4282 @safe unittest
4284 enum E { member, a = 0, b = 0 }
4285 static assert(__traits(identifier, EnumMembers!E[0]) == "member");
4286 static assert(__traits(identifier, EnumMembers!E[1]) == "a");
4287 static assert(__traits(identifier, EnumMembers!E[2]) == "b");
4291 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4292 // Classes and Interfaces
4293 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4295 /***
4296 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
4297 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
4298 * the empty type tuple.
4300 template BaseTypeTuple(A)
4302 static if (is(A P == super))
4303 alias BaseTypeTuple = P;
4304 else
4305 static assert(0, "argument is not a class or interface");
4309 @safe unittest
4311 import std.meta : AliasSeq;
4313 interface I1 { }
4314 interface I2 { }
4315 interface I12 : I1, I2 { }
4316 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));
4318 interface I3 : I1 { }
4319 interface I123 : I1, I2, I3 { }
4320 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));
4323 @safe unittest
4325 interface I1 { }
4326 interface I2 { }
4327 class A { }
4328 class C : A, I1, I2 { }
4330 alias TL = BaseTypeTuple!C;
4331 assert(TL.length == 3);
4332 assert(is (TL[0] == A));
4333 assert(is (TL[1] == I1));
4334 assert(is (TL[2] == I2));
4336 assert(BaseTypeTuple!Object.length == 0);
4340 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4341 * in decreasing order. Interfaces are not included. $(D_PARAM
4342 * BaseClassesTuple!Object) yields the empty type tuple.
4344 template BaseClassesTuple(T)
4345 if (is(T == class))
4347 static if (is(T == Object))
4349 alias BaseClassesTuple = AliasSeq!();
4351 else static if (is(BaseTypeTuple!T[0] == Object))
4353 alias BaseClassesTuple = AliasSeq!Object;
4355 else static if (!is(BaseTypeTuple!T[0] == Object) && !is(BaseTypeTuple!T[0] == class))
4357 alias BaseClassesTuple = AliasSeq!();
4359 else
4361 alias BaseClassesTuple =
4362 AliasSeq!(BaseTypeTuple!T[0],
4363 BaseClassesTuple!(BaseTypeTuple!T[0]));
4368 @safe unittest
4370 import std.meta : AliasSeq;
4372 class C1 { }
4373 class C2 : C1 { }
4374 class C3 : C2 { }
4375 static assert(!BaseClassesTuple!Object.length);
4376 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
4377 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
4378 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));
4381 // https://issues.dlang.org/show_bug.cgi?id=17276
4382 @safe unittest
4384 extern (C++) static interface Ext
4386 void someext();
4389 extern (C++) static class E : Ext
4391 void someext() {}
4394 alias BaseClassesWithNoObject = BaseClassesTuple!E;
4397 @safe unittest
4399 struct S { }
4400 static assert(!__traits(compiles, BaseClassesTuple!S));
4401 interface I { }
4402 static assert(!__traits(compiles, BaseClassesTuple!I));
4403 class C4 : I { }
4404 class C5 : C4, I { }
4405 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object)));
4409 Params:
4410 T = The `class` or `interface` to search.
4412 Returns:
4413 $(REF AliasSeq,std,meta) of all interfaces directly or
4414 indirectly inherited by this class or interface. Interfaces
4415 do not repeat if multiply implemented.
4417 `InterfacesTuple!Object` yields an empty `AliasSeq`.
4419 template InterfacesTuple(T)
4421 import std.meta : NoDuplicates;
4422 template Flatten(H, T...)
4424 static if (T.length)
4426 alias Flatten = AliasSeq!(Flatten!H, Flatten!T);
4428 else
4430 static if (is(H == interface))
4431 alias Flatten = AliasSeq!(H, InterfacesTuple!H);
4432 else
4433 alias Flatten = InterfacesTuple!H;
4437 static if (is(T S == super) && S.length)
4438 alias InterfacesTuple = NoDuplicates!(Flatten!S);
4439 else
4440 alias InterfacesTuple = AliasSeq!();
4444 @safe unittest
4446 interface I1 {}
4447 interface I2 {}
4448 class A : I1, I2 {}
4449 class B : A, I1 {}
4450 class C : B {}
4452 alias TL = InterfacesTuple!C;
4453 static assert(is(TL[0] == I1) && is(TL[1] == I2));
4456 @safe unittest
4458 interface Iaa {}
4459 interface Iab {}
4460 interface Iba {}
4461 interface Ibb {}
4462 interface Ia : Iaa, Iab {}
4463 interface Ib : Iba, Ibb {}
4464 interface I : Ia, Ib {}
4465 interface J {}
4466 class B2 : J {}
4467 class C2 : B2, Ia, Ib {}
4468 static assert(is(InterfacesTuple!I ==
4469 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb)));
4470 static assert(is(InterfacesTuple!C2 ==
4471 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb)));
4476 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4477 * T), in decreasing order, followed by $(D_PARAM T)'s
4478 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4479 * empty type tuple.
4481 alias TransitiveBaseTypeTuple(T) = AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
4484 @safe unittest
4486 interface J1 {}
4487 interface J2 {}
4488 class B1 {}
4489 class B2 : B1, J1, J2 {}
4490 class B3 : B2, J1 {}
4491 alias TL = TransitiveBaseTypeTuple!B3;
4492 assert(TL.length == 5);
4493 assert(is (TL[0] == B2));
4494 assert(is (TL[1] == B1));
4495 assert(is (TL[2] == Object));
4496 assert(is (TL[3] == J1));
4497 assert(is (TL[4] == J2));
4499 assert(TransitiveBaseTypeTuple!Object.length == 0);
4504 Returns a tuple of non-static functions with the name `name` declared in the
4505 class or interface `C`. Covariant duplicates are shrunk into the most
4506 derived one.
4508 template MemberFunctionsTuple(C, string name)
4509 if (is(C == class) || is(C == interface))
4511 static if (__traits(hasMember, C, name))
4514 * First, collect all overloads in the class hierarchy.
4516 template CollectOverloads(Node)
4518 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
4520 // Get all overloads in sight (not hidden).
4521 alias inSight = __traits(getVirtualMethods, Node, name);
4523 // And collect all overloads in ancestor classes to reveal hidden
4524 // methods. The result may contain duplicates.
4525 template walkThru(Parents...)
4527 static if (Parents.length > 0)
4528 alias walkThru = AliasSeq!(
4529 CollectOverloads!(Parents[0]),
4530 walkThru!(Parents[1 .. $])
4532 else
4533 alias walkThru = AliasSeq!();
4536 static if (is(Node Parents == super))
4537 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents);
4538 else
4539 alias CollectOverloads = AliasSeq!inSight;
4541 else
4542 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy
4545 static if (name == "__ctor" || name == "__dtor")
4546 alias overloads = AliasSeq!(__traits(getOverloads, C, name));
4547 else
4548 // duplicates in this tuple will be removed by shrink()
4549 alias overloads = CollectOverloads!C;
4551 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4552 // shrinkOne!args[1..$] = non-covariant others
4553 template shrinkOne(/+ alias target, rest... +/ args...)
4555 import std.meta : AliasSeq;
4556 alias target = args[0 .. 1]; // prevent property functions from being evaluated
4557 alias rest = args[1 .. $];
4559 static if (rest.length > 0)
4561 alias Target = FunctionTypeOf!target;
4562 alias Rest0 = FunctionTypeOf!(rest[0]);
4564 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target))
4566 // One of these overrides the other. Choose the one from the most derived parent.
4567 static if (is(__traits(parent, target) : __traits(parent, rest[0])))
4568 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4569 else
4570 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4572 else static if (isCovariantWith!(Target, Rest0))
4573 // target overrides rest[0] -- erase rest[0].
4574 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4575 else static if (isCovariantWith!(Rest0, Target))
4576 // rest[0] overrides target -- erase target.
4577 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4578 else
4579 // target and rest[0] are distinct.
4580 alias shrinkOne = AliasSeq!(
4581 shrinkOne!(target, rest[1 .. $]),
4582 rest[0] // keep
4585 else
4586 alias shrinkOne = AliasSeq!target; // done
4590 * Now shrink covariant overloads into one.
4592 template shrink(overloads...)
4594 static if (overloads.length > 0)
4596 alias temp = shrinkOne!overloads;
4597 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $]));
4599 else
4600 alias shrink = AliasSeq!(); // done
4603 // done.
4604 alias MemberFunctionsTuple = shrink!overloads;
4606 else
4607 alias MemberFunctionsTuple = AliasSeq!();
4611 @safe unittest
4613 interface I { I foo(); }
4614 class B
4616 real foo(real v) { return v; }
4618 class C : B, I
4620 override C foo() { return this; } // covariant overriding of I.foo()
4622 alias foos = MemberFunctionsTuple!(C, "foo");
4623 static assert(foos.length == 2);
4624 static assert(__traits(isSame, foos[0], C.foo));
4625 static assert(__traits(isSame, foos[1], B.foo));
4628 // https://issues.dlang.org/show_bug.cgi?id=15920
4629 @safe unittest
4631 import std.meta : AliasSeq;
4632 class A
4634 void f(){}
4635 void f(int){}
4637 class B : A
4639 override void f(){}
4640 override void f(int){}
4642 alias fs = MemberFunctionsTuple!(B, "f");
4643 alias bfs = __traits(getOverloads, B, "f");
4644 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1]));
4645 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1]));
4648 // https://issues.dlang.org/show_bug.cgi?id=8388
4649 @safe unittest
4651 class C
4653 this() {}
4654 this(int i) {}
4655 this(int i, float j) {}
4656 this(string s) {}
4659 Commented out, because this causes a cyclic dependency
4660 between module constructors/destructors error. Might
4661 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */
4662 // static this() {}
4664 ~this() {}
4667 class D : C
4669 this() {}
4670 ~this() {}
4673 alias test_ctor = MemberFunctionsTuple!(C, "__ctor");
4674 assert(test_ctor.length == 4);
4675 alias test_dtor = MemberFunctionsTuple!(C, "__dtor");
4676 assert(test_dtor.length == 1);
4677 alias test2_ctor = MemberFunctionsTuple!(D, "__ctor");
4678 assert(test2_ctor.length == 1);
4679 alias test2_dtor = MemberFunctionsTuple!(D, "__dtor");
4680 assert(test2_dtor.length == 1);
4683 @safe unittest
4685 interface I { I test(); }
4686 interface J : I { J test(); }
4687 interface K { K test(int); }
4688 class B : I, K
4690 K test(int) { return this; }
4691 B test() { return this; }
4692 static void test(string) { }
4694 class C : B, J
4696 override C test() { return this; }
4698 alias test =MemberFunctionsTuple!(C, "test");
4699 static assert(test.length == 2);
4700 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test)));
4701 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test)));
4702 alias noexist = MemberFunctionsTuple!(C, "noexist");
4703 static assert(noexist.length == 0);
4705 interface L { int prop() @property; }
4706 alias prop = MemberFunctionsTuple!(L, "prop");
4707 static assert(prop.length == 1);
4709 interface Test_I
4711 void foo();
4712 void foo(int);
4713 void foo(int, int);
4715 interface Test : Test_I {}
4716 alias Test_foo = MemberFunctionsTuple!(Test, "foo");
4717 static assert(Test_foo.length == 3);
4718 static assert(is(typeof(&Test_foo[0]) == void function()));
4719 static assert(is(typeof(&Test_foo[2]) == void function(int)));
4720 static assert(is(typeof(&Test_foo[1]) == void function(int, int)));
4725 Returns an alias to the template that `T` is an instance of.
4726 It will return `void` if a symbol without a template is given.
4728 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
4730 /// ditto
4731 alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
4733 /// ditto
4734 alias TemplateOf(T) = void;
4737 @safe unittest
4739 struct Foo(T, U) {}
4740 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4743 @safe unittest
4745 template Foo1(A) {}
4746 template Foo2(A, B) {}
4747 template Foo3(alias A) {}
4748 template Foo4(string A) {}
4749 struct Foo5(A) {}
4750 struct Foo6(A, B) {}
4751 struct Foo7(alias A) {}
4752 template Foo8(A) { template Foo9(B) {} }
4753 template Foo10() {}
4755 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4756 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4757 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4758 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4759 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4760 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4761 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4762 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4763 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4766 // https://issues.dlang.org/show_bug.cgi?id=18214
4767 @safe unittest
4769 static assert(is(TemplateOf!(int[]) == void));
4770 static assert(is(TemplateOf!bool == void));
4774 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4776 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4778 /// ditto
4779 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4782 @safe unittest
4784 import std.meta : AliasSeq;
4786 struct Foo(T, U) {}
4787 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4790 @safe unittest
4792 template Foo1(A) {}
4793 template Foo2(A, B) {}
4794 template Foo3(alias A) {}
4795 template Foo4(string A) {}
4796 struct Foo5(A) {}
4797 struct Foo6(A, B) {}
4798 struct Foo7(alias A) {}
4799 template Foo8(A) { template Foo9(B) {} }
4800 template Foo10() {}
4802 enum x = 123;
4803 enum y = "123";
4804 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4805 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4806 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4807 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4808 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4809 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4810 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4811 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4812 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4815 // Returns the largest alignment in a type tuple.
4816 package enum maxAlignment(U...) =
4818 size_t result = U[0].alignof;
4819 static foreach (T; U[1 .. $])
4820 if (result < T.alignof)
4821 result = T.alignof;
4822 return result;
4823 }();
4826 Returns class instance alignment.
4828 See also: $(DDSUBLINK spec/traits, classInstanceAlignment, `__traits(classInstanceAlignment, T)`)
4830 template classInstanceAlignment(T)
4831 if (is(T == class))
4833 enum classInstanceAlignment = __traits(classInstanceAlignment, T);
4837 @safe unittest
4839 class A { byte b; }
4840 class B { long l; }
4842 // As class instance always has a hidden pointer
4843 static assert(classInstanceAlignment!A == (void*).alignof);
4844 static assert(classInstanceAlignment!B == long.alignof);
4848 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4849 // Type Conversion
4850 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4853 Get the type that all types can be implicitly converted to. Useful
4854 e.g. in figuring out an array type from a bunch of initializing
4855 values. Returns $(D_PARAM void) if passed an empty list, or if the
4856 types have no common type.
4858 template CommonType(T...)
4860 static if (T.length == 1)
4861 alias CommonType = typeof(T[0].init);
4862 else static if (is(typeof(true ? T[0].init : T[1].init) U))
4863 alias CommonType = CommonType!(U, T[2 .. $]);
4864 else
4865 alias CommonType = void;
4869 @safe unittest
4871 alias X = CommonType!(int, long, short);
4872 assert(is(X == long));
4873 alias Y = CommonType!(int, char[], short);
4874 assert(is(Y == void));
4878 @safe unittest
4880 static assert(is(CommonType!(3) == int));
4881 static assert(is(CommonType!(double, 4, float) == double));
4882 static assert(is(CommonType!(string, char[]) == const(char)[]));
4883 static assert(is(CommonType!(3, 3U) == uint));
4884 static assert(is(CommonType!(double, int) == double));
4889 Params:
4890 T = The type to check
4892 Returns:
4893 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4894 conversion `T`.
4896 If `T` is a class derived from `Object`, the result of
4897 $(LREF TransitiveBaseTypeTuple) is returned.
4899 If the type is not a built-in value type or a class derived from
4900 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4902 See_Also:
4903 $(LREF isImplicitlyConvertible)
4905 template AllImplicitConversionTargets(T)
4907 static if (is(T == bool))
4908 alias AllImplicitConversionTargets =
4909 AliasSeq!(byte, AllImplicitConversionTargets!byte);
4910 else static if (is(T == byte))
4911 alias AllImplicitConversionTargets =
4912 AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4913 else static if (is(T == ubyte))
4914 alias AllImplicitConversionTargets =
4915 AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4916 else static if (is(T == short))
4917 alias AllImplicitConversionTargets =
4918 AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4919 else static if (is(T == ushort))
4920 alias AllImplicitConversionTargets =
4921 AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4922 else static if (is(T == int))
4923 alias AllImplicitConversionTargets =
4924 AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4925 else static if (is(T == uint))
4926 alias AllImplicitConversionTargets =
4927 AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4928 else static if (is(T == long))
4929 alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4930 else static if (is(T == ulong))
4931 alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4932 else static if (is(T == float))
4933 alias AllImplicitConversionTargets = AliasSeq!(double, real);
4934 else static if (is(T == double))
4935 alias AllImplicitConversionTargets = AliasSeq!(float, real);
4936 else static if (is(T == real))
4937 alias AllImplicitConversionTargets = AliasSeq!(float, double);
4938 else static if (is(T == char))
4939 alias AllImplicitConversionTargets =
4940 AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4941 else static if (is(T == wchar))
4942 alias AllImplicitConversionTargets =
4943 AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4944 else static if (is(T == dchar))
4945 alias AllImplicitConversionTargets =
4946 AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4947 else static if (is(T == class))
4948 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4949 else static if (is(T == interface))
4950 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4951 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4953 static if (is(typeof(T.init[0]) == shared))
4954 alias AllImplicitConversionTargets =
4955 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4956 else
4957 alias AllImplicitConversionTargets =
4958 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4960 else static if (is(T : void*) && !is(T == void*))
4961 alias AllImplicitConversionTargets = AliasSeq!(void*);
4962 else static if (is(cent) && is(T == cent))
4963 alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4964 else static if (is(ucent) && is(T == ucent))
4965 alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4966 else
4967 alias AllImplicitConversionTargets = AliasSeq!();
4971 @safe unittest
4973 import std.meta : AliasSeq;
4975 static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4976 static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4977 static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4978 static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4980 static assert(is(AllImplicitConversionTargets!(char) ==
4981 AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4982 ulong, float, double, real)
4984 static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4985 short, ushort, dchar, int, uint, long, ulong, float, double, real
4986 )));
4987 static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
4988 int, uint, long, ulong, float, double, real
4989 )));
4991 static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
4992 static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
4994 interface A {}
4995 interface B {}
4996 class C : A, B {}
4998 static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
4999 static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5000 static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
5001 immutable Object, immutable A, immutable B
5002 )));
5004 interface I : A, B {}
5006 static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
5007 static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
5008 static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
5009 immutable A, immutable B
5010 )));
5013 @safe unittest
5015 static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5016 static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5017 static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5022 Params:
5023 T = The type to check
5025 Warning:
5026 This template is considered out-dated. It will be removed from
5027 Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5029 Returns:
5030 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5031 conversion `T`.
5033 If `T` is a class derived from `Object`, the result of
5034 $(LREF TransitiveBaseTypeTuple) is returned.
5036 If the type is not a built-in value type or a class derived from
5037 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5039 Note:
5040 The possible targets are computed more conservatively than the
5041 language allows, eliminating all dangerous conversions. For example,
5042 `ImplicitConversionTargets!double` does not include `float`.
5044 See_Also:
5045 $(LREF isImplicitlyConvertible)
5047 // @@@DEPRECATED_[2.107.0]@@@
5048 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5049 ~ "and will be removed in 2.107.0")
5050 template ImplicitConversionTargets(T)
5052 static if (is(T == bool))
5053 alias ImplicitConversionTargets =
5054 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5055 float, double, real, char, wchar, dchar);
5056 else static if (is(T == byte))
5057 alias ImplicitConversionTargets =
5058 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5059 float, double, real, char, wchar, dchar);
5060 else static if (is(T == ubyte))
5061 alias ImplicitConversionTargets =
5062 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5063 float, double, real, char, wchar, dchar);
5064 else static if (is(T == short))
5065 alias ImplicitConversionTargets =
5066 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5067 else static if (is(T == ushort))
5068 alias ImplicitConversionTargets =
5069 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5070 else static if (is(T == int))
5071 alias ImplicitConversionTargets =
5072 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5073 else static if (is(T == uint))
5074 alias ImplicitConversionTargets =
5075 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5076 else static if (is(T == long))
5077 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5078 else static if (is(T == ulong))
5079 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5080 else static if (is(cent) && is(T == cent))
5081 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5082 else static if (is(ucent) && is(T == ucent))
5083 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5084 else static if (is(T == float))
5085 alias ImplicitConversionTargets = AliasSeq!(double, real);
5086 else static if (is(T == double))
5087 alias ImplicitConversionTargets = AliasSeq!real;
5088 else static if (is(T == char))
5089 alias ImplicitConversionTargets =
5090 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5091 int, uint, long, ulong, CentTypeList, float, double, real);
5092 else static if (is(T == wchar))
5093 alias ImplicitConversionTargets =
5094 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5095 float, double, real);
5096 else static if (is(T == dchar))
5097 alias ImplicitConversionTargets =
5098 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5099 else static if (is(T : typeof(null)))
5100 alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5101 else static if (is(T == class))
5102 alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5103 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5105 static if (is(typeof(T.init[0]) == shared))
5106 alias ImplicitConversionTargets =
5107 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5108 else
5109 alias ImplicitConversionTargets =
5110 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5112 else static if (is(T : void*))
5113 alias ImplicitConversionTargets = AliasSeq!(void*);
5114 else
5115 alias ImplicitConversionTargets = AliasSeq!();
5118 deprecated @safe unittest
5120 import std.meta : AliasSeq;
5122 static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5123 static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5124 static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5125 static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5127 static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5128 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5129 )));
5130 static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5131 dchar, short, ushort, int, uint, long, ulong, float, double, real
5132 )));
5133 static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5134 int, uint, long, ulong, float, double, real
5135 )));
5137 static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5138 static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5140 interface A {}
5141 interface B {}
5142 class C : A, B {}
5144 static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5145 static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5146 static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5147 immutable Object, immutable A, immutable B
5148 )));
5151 deprecated @safe unittest
5153 static assert(is(ImplicitConversionTargets!(double)[0] == real));
5154 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5158 Is `From` implicitly convertible to `To`?
5160 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5163 @safe unittest
5165 static assert( isImplicitlyConvertible!(immutable(char), char));
5166 static assert( isImplicitlyConvertible!(const(char), char));
5167 static assert( isImplicitlyConvertible!(char, wchar));
5168 static assert(!isImplicitlyConvertible!(wchar, char));
5170 static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5171 static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5172 static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5174 static assert(!isImplicitlyConvertible!(const(char)[], string));
5175 static assert( isImplicitlyConvertible!(string, const(char)[]));
5179 Is `From` $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) to `To`?
5181 enum bool isQualifierConvertible(From, To) =
5182 is(immutable From == immutable To) && is(From* : To*);
5185 @safe unittest
5187 // Mutable and immmutable both convert to const...
5188 static assert( isQualifierConvertible!(char, const(char)));
5189 static assert( isQualifierConvertible!(immutable(char), const(char)));
5190 // ...but const does not convert back to mutable or immutable
5191 static assert(!isQualifierConvertible!(const(char), char));
5192 static assert(!isQualifierConvertible!(const(char), immutable(char)));
5195 @safe unittest
5197 import std.meta : AliasSeq;
5199 alias Ts = AliasSeq!(int, const int, shared int, inout int, const shared int,
5200 const inout int, inout shared int, const inout shared int, immutable int);
5202 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
5203 enum _ = 0;
5204 static immutable bool[Ts.length][Ts.length] conversions = [
5205 // m c s i cs ci is cis im
5206 [1, 1, _, _, _, _, _, _, _], // mutable
5207 [_, 1, _, _, _, _, _, _, _], // const
5208 [_, _, 1, _, 1, _, _, _, _], // shared
5209 [_, 1, _, 1, _, 1, _, _, _], // inout
5210 [_, _, _, _, 1, _, _, _, _], // const shared
5211 [_, 1, _, _, _, 1, _, _, _], // const inout
5212 [_, _, _, _, 1, _, 1, 1, _], // inout shared
5213 [_, _, _, _, 1, _, _, 1, _], // const inout shared
5214 [_, 1, _, _, 1, 1, _, 1, 1], // immutable
5217 static foreach (i, From; Ts)
5219 static foreach (j, To; Ts)
5221 static assert(isQualifierConvertible!(From, To) == conversions[i][j],
5222 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`"
5223 ~ " should be `" ~ (conversions[i][j] ? "true" : "false") ~ "`");
5228 @safe unittest
5230 // int* -> void* is not a qualifier conversion
5231 static assert(!isQualifierConvertible!(int, void));
5235 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5236 type `Lhs`.
5238 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5240 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5242 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5245 @safe unittest
5247 static assert( isAssignable!(long, int));
5248 static assert(!isAssignable!(int, long));
5249 static assert( isAssignable!(const(char)[], string));
5250 static assert(!isAssignable!(string, char[]));
5252 // int is assignable to int
5253 static assert( isAssignable!int);
5255 // immutable int is not assignable to immutable int
5256 static assert(!isAssignable!(immutable int));
5260 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5261 type `Lhs`.
5263 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5266 @safe unittest
5268 struct S1
5270 void opAssign(S1);
5273 struct S2
5275 void opAssign(ref S2);
5278 static assert( isRvalueAssignable!(long, int));
5279 static assert(!isRvalueAssignable!(int, long));
5280 static assert( isRvalueAssignable!S1);
5281 static assert(!isRvalueAssignable!S2);
5285 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5286 type `Lhs`.
5288 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5291 @safe unittest
5293 struct S1
5295 void opAssign(S1);
5298 struct S2
5300 void opAssign(ref S2);
5303 static assert( isLvalueAssignable!(long, int));
5304 static assert(!isLvalueAssignable!(int, long));
5305 static assert( isLvalueAssignable!S1);
5306 static assert( isLvalueAssignable!S2);
5309 @safe unittest
5311 static assert(!isAssignable!(immutable int, int));
5312 static assert( isAssignable!(int, immutable int));
5314 static assert(!isAssignable!(inout int, int));
5315 static assert( isAssignable!(int, inout int));
5316 static assert(!isAssignable!(inout int));
5318 static assert( isAssignable!(shared int, int));
5319 static assert( isAssignable!(int, shared int));
5320 static assert( isAssignable!(shared int));
5322 static assert( isAssignable!(void[1], void[1]));
5324 struct S { @disable this(); this(int n){} }
5325 static assert( isAssignable!(S, S));
5327 struct S2 { this(int n){} }
5328 static assert( isAssignable!(S2, S2));
5329 static assert(!isAssignable!(S2, int));
5331 struct S3 { @disable void opAssign(); }
5332 static assert( isAssignable!(S3, S3));
5334 struct S3X { @disable void opAssign(S3X); }
5335 static assert(!isAssignable!(S3X, S3X));
5337 struct S4 { void opAssign(int); }
5338 static assert( isAssignable!(S4, S4));
5339 static assert( isAssignable!(S4, int));
5340 static assert( isAssignable!(S4, immutable int));
5342 struct S5 { @disable this(); @disable this(this); }
5343 // https://issues.dlang.org/show_bug.cgi?id=21210
5344 static assert(!isAssignable!S5);
5346 // `-preview=in` is enabled
5347 alias DScannerBug895 = int[256];
5348 static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
5350 struct S6 { void opAssign(in S5); }
5352 static assert(isRvalueAssignable!(S6, S5));
5353 static assert(isLvalueAssignable!(S6, S5));
5354 static assert(isAssignable!(S6, S5));
5355 static assert(isAssignable!(S6, immutable S5));
5357 else
5359 mixin(q{ struct S6 { void opAssign(scope const ref S5); } });
5361 static assert(!isRvalueAssignable!(S6, S5));
5362 static assert( isLvalueAssignable!(S6, S5));
5363 static assert(!isAssignable!(S6, S5));
5364 static assert( isLvalueAssignable!(S6, immutable S5));
5369 // Equivalent with TypeStruct::isAssignable in compiler code.
5370 package template isBlitAssignable(T)
5372 static if (is(T == enum))
5374 enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5376 else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5377 // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary.
5379 enum isBlitAssignable = isBlitAssignable!E;
5381 else static if (is(T == struct) || is(T == union))
5383 enum isBlitAssignable = isMutable!T &&
5385 size_t offset = 0;
5386 bool assignable = true;
5387 foreach (i, F; FieldTypeTuple!T)
5389 static if (i == 0)
5392 else
5394 if (T.tupleof[i].offsetof == offset)
5396 if (assignable)
5397 continue;
5399 else
5401 if (!assignable)
5402 return false;
5405 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5406 offset = T.tupleof[i].offsetof;
5408 return assignable;
5409 }();
5411 else
5412 enum isBlitAssignable = isMutable!T;
5415 @safe unittest
5417 static assert( isBlitAssignable!int);
5418 static assert(!isBlitAssignable!(const int));
5420 class C{ const int i; }
5421 static assert( isBlitAssignable!C);
5423 struct S1{ int i; }
5424 struct S2{ const int i; }
5425 static assert( isBlitAssignable!S1);
5426 static assert(!isBlitAssignable!S2);
5428 struct S3X { union { int x; int y; } }
5429 struct S3Y { union { int x; const int y; } }
5430 struct S3Z { union { const int x; const int y; } }
5431 static assert( isBlitAssignable!(S3X));
5432 static assert( isBlitAssignable!(S3Y));
5433 static assert(!isBlitAssignable!(S3Z));
5434 static assert(!isBlitAssignable!(const S3X));
5435 static assert(!isBlitAssignable!(inout S3Y));
5436 static assert(!isBlitAssignable!(immutable S3Z));
5437 static assert( isBlitAssignable!(S3X[3]));
5438 static assert( isBlitAssignable!(S3Y[3]));
5439 static assert(!isBlitAssignable!(S3Z[3]));
5440 enum ES3X : S3X { a = S3X() }
5441 enum ES3Y : S3Y { a = S3Y() }
5442 enum ES3Z : S3Z { a = S3Z() }
5443 static assert( isBlitAssignable!(ES3X));
5444 static assert( isBlitAssignable!(ES3Y));
5445 static assert(!isBlitAssignable!(ES3Z));
5446 static assert(!isBlitAssignable!(const ES3X));
5447 static assert(!isBlitAssignable!(inout ES3Y));
5448 static assert(!isBlitAssignable!(immutable ES3Z));
5449 static assert( isBlitAssignable!(ES3X[3]));
5450 static assert( isBlitAssignable!(ES3Y[3]));
5451 static assert(!isBlitAssignable!(ES3Z[3]));
5453 union U1X { int x; int y; }
5454 union U1Y { int x; const int y; }
5455 union U1Z { const int x; const int y; }
5456 static assert( isBlitAssignable!(U1X));
5457 static assert( isBlitAssignable!(U1Y));
5458 static assert(!isBlitAssignable!(U1Z));
5459 static assert(!isBlitAssignable!(const U1X));
5460 static assert(!isBlitAssignable!(inout U1Y));
5461 static assert(!isBlitAssignable!(immutable U1Z));
5462 static assert( isBlitAssignable!(U1X[3]));
5463 static assert( isBlitAssignable!(U1Y[3]));
5464 static assert(!isBlitAssignable!(U1Z[3]));
5465 enum EU1X : U1X { a = U1X() }
5466 enum EU1Y : U1Y { a = U1Y() }
5467 enum EU1Z : U1Z { a = U1Z() }
5468 static assert( isBlitAssignable!(EU1X));
5469 static assert( isBlitAssignable!(EU1Y));
5470 static assert(!isBlitAssignable!(EU1Z));
5471 static assert(!isBlitAssignable!(const EU1X));
5472 static assert(!isBlitAssignable!(inout EU1Y));
5473 static assert(!isBlitAssignable!(immutable EU1Z));
5474 static assert( isBlitAssignable!(EU1X[3]));
5475 static assert( isBlitAssignable!(EU1Y[3]));
5476 static assert(!isBlitAssignable!(EU1Z[3]));
5478 struct SA
5480 @property int[3] foo() { return [1,2,3]; }
5481 alias foo this;
5482 const int x; // SA is not blit assignable
5484 static assert(!isStaticArray!SA);
5485 static assert(!isBlitAssignable!(SA[3]));
5490 Works like `isImplicitlyConvertible`, except this cares only about storage
5491 classes of the arguments.
5493 private template isStorageClassImplicitlyConvertible(From, To)
5495 alias Pointify(T) = void*;
5497 enum isStorageClassImplicitlyConvertible = is(
5498 ModifyTypePreservingTQ!(Pointify, From) :
5499 ModifyTypePreservingTQ!(Pointify, To) );
5502 @safe unittest
5504 static assert( isStorageClassImplicitlyConvertible!( int, const int));
5505 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5507 static assert(!isStorageClassImplicitlyConvertible!(const int, int));
5508 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5509 static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5510 static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5515 Determines whether the function type `F` is covariant with `G`, i.e.,
5516 functions of the type `F` can override ones of the type `G`.
5518 template isCovariantWith(F, G)
5519 if (is(F == function) && is(G == function) ||
5520 is(F == delegate) && is(G == delegate) ||
5521 isFunctionPointer!F && isFunctionPointer!G)
5523 static if (is(F : G))
5524 enum isCovariantWith = true;
5525 else
5527 alias Upr = F;
5528 alias Lwr = G;
5531 * Check for calling convention: require exact match.
5533 template checkLinkage()
5535 enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5538 * Check for variadic parameter: require exact match.
5540 template checkVariadicity()
5542 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5545 * Check for function storage class:
5546 * - overrider can have narrower storage class than base
5548 template checkSTC()
5550 // Note the order of arguments. The convertion order Lwr -> Upr is
5551 // correct since Upr should be semantically 'narrower' than Lwr.
5552 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5555 * Check for function attributes:
5556 * - require exact match for ref and @property
5557 * - overrider can add pure and nothrow, but can't remove them
5558 * - @safe and @trusted are covariant with each other, unremovable
5560 template checkAttributes()
5562 alias FA = FunctionAttribute;
5563 enum uprAtts = functionAttributes!Upr;
5564 enum lwrAtts = functionAttributes!Lwr;
5566 enum wantExact = FA.ref_ | FA.property;
5567 enum safety = FA.safe | FA.trusted;
5568 enum ok =
5569 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) &&
5570 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) &&
5571 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5572 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ;
5575 * Check for return type: usual implicit convertion.
5577 template checkReturnType()
5579 enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5582 * Check for parameters:
5583 * - require exact match for types
5584 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5585 * - require exact match for in, out, ref and lazy
5586 * - overrider can add scope, but can't remove
5588 template checkParameters()
5590 alias STC = ParameterStorageClass;
5591 alias UprParams = Parameters!Upr;
5592 alias LwrParams = Parameters!Lwr;
5593 alias UprPSTCs = ParameterStorageClassTuple!Upr;
5594 alias LwrPSTCs = ParameterStorageClassTuple!Lwr;
5596 template checkNext(size_t i)
5598 static if (i < UprParams.length)
5600 enum uprStc = UprPSTCs[i];
5601 enum lwrStc = LwrPSTCs[i];
5603 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5604 enum ok =
5605 ((uprStc & wantExact ) == (lwrStc & wantExact )) &&
5606 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) &&
5607 checkNext!(i + 1).ok;
5609 else
5610 enum ok = true; // done
5612 static if (UprParams.length == LwrParams.length)
5613 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5614 else
5615 enum ok = false;
5618 /* run all the checks */
5619 enum isCovariantWith =
5620 checkLinkage !().ok &&
5621 checkVariadicity!().ok &&
5622 checkSTC !().ok &&
5623 checkAttributes !().ok &&
5624 checkReturnType !().ok &&
5625 checkParameters !().ok ;
5630 @safe unittest
5632 interface I { I clone(); }
5633 interface J { J clone(); }
5634 class C : I
5636 override C clone() // covariant overriding of I.clone()
5638 return new C;
5642 // C.clone() can override I.clone(), indeed.
5643 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5645 // C.clone() can't override J.clone(); the return type C is not implicitly
5646 // convertible to J.
5647 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5650 @safe unittest
5652 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5654 // covariant return type
5655 interface I {}
5656 interface J : I {}
5657 interface BaseA { const(I) test(int); }
5658 interface DerivA_1 : BaseA { override const(J) test(int); }
5659 interface DerivA_2 : BaseA { override J test(int); }
5660 static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5661 static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5662 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5663 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5664 static assert( isCovariantWith!(BaseA.test, BaseA.test));
5665 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5666 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5668 // function, function pointer and delegate
5669 J function() derived_function;
5670 I function() base_function;
5671 J delegate() derived_delegate;
5672 I delegate() base_delegate;
5673 static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5674 static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5675 static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5677 // scope parameter
5678 interface BaseB { void test( int*, int*); }
5679 interface DerivB_1 : BaseB { override void test(scope int*, int*); }
5680 interface DerivB_2 : BaseB { override void test( int*, scope int*); }
5681 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5682 static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5683 static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5684 static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5685 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5686 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5687 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5689 // function storage class
5690 interface BaseC { void test() ; }
5691 interface DerivC_1 : BaseC { override void test() const; }
5692 static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5693 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5695 // increasing safety
5696 interface BaseE { void test() ; }
5697 interface DerivE_1 : BaseE { override void test() @safe ; }
5698 interface DerivE_2 : BaseE { override void test() @trusted; }
5699 static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5700 static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5701 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5702 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5704 // @safe and @trusted
5705 interface BaseF
5707 void test1() @safe;
5708 void test2() @trusted;
5710 interface DerivF : BaseF
5712 override void test1() @trusted;
5713 override void test2() @safe;
5715 static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5716 static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5720 // Needed for rvalueOf/lvalueOf because "inout on return means
5721 // inout must be on a parameter as well"
5722 private struct __InoutWorkaroundStruct{}
5725 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5726 $(DDSUBLINK spec/traits, compiles, `__traits(compiles, ...)`) purposes. No actual value is returned.
5728 Params:
5729 T = The type to transform
5731 Note: Trying to use returned value will result in a
5732 "Symbol Undefined" error at link time.
5734 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5736 /// ditto
5737 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5739 // Note: can't put these unittests together as function overloads
5740 // aren't allowed inside functions.
5742 @system unittest
5744 static int f(int);
5745 static assert(is(typeof(f(rvalueOf!int)) == int));
5749 @system unittest
5751 static bool f(ref int);
5752 static assert(is(typeof(f(lvalueOf!int)) == bool));
5755 @system unittest
5757 void needLvalue(T)(ref T);
5758 static struct S { }
5759 int i;
5760 struct Nested { void f() { ++i; } }
5761 static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5763 static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5764 static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5765 static assert(is(typeof(rvalueOf!T) == T));
5766 static assert(is(typeof(lvalueOf!T) == T));
5769 static assert(!__traits(compiles, rvalueOf!int = 1));
5770 static assert( __traits(compiles, lvalueOf!byte = 127));
5771 static assert(!__traits(compiles, lvalueOf!byte = 128));
5775 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5776 // SomethingTypeOf
5777 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5781 template BooleanTypeOf(T)
5783 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5784 alias X = BooleanTypeOf!AT;
5785 else
5786 alias X = OriginalType!T;
5788 static if (is(immutable X == immutable bool))
5790 alias BooleanTypeOf = X;
5792 else
5793 static assert(0, T.stringof~" is not boolean type");
5796 @safe unittest
5798 // unexpected failure, maybe dmd type-merging bug
5799 static foreach (T; AliasSeq!bool)
5800 static foreach (Q; TypeQualifierList)
5802 static assert( is(Q!T == BooleanTypeOf!( Q!T )));
5803 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5806 static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5807 static foreach (Q; TypeQualifierList)
5809 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof);
5810 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5814 @safe unittest
5816 struct B
5818 bool val;
5819 alias val this;
5821 struct S
5823 B b;
5824 alias b this;
5826 static assert(is(BooleanTypeOf!B == bool));
5827 static assert(is(BooleanTypeOf!S == bool));
5832 template IntegralTypeOf(T)
5834 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5835 alias X = IntegralTypeOf!AT;
5836 else
5837 alias X = OriginalType!T;
5839 static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5840 && !is(immutable X == immutable bool) && !is(X == __vector))
5842 alias IntegralTypeOf = X;
5844 else
5845 static assert(0, T.stringof~" is not an integral type");
5848 @safe unittest
5850 static foreach (T; IntegralTypeList)
5851 static foreach (Q; TypeQualifierList)
5853 static assert( is(Q!T == IntegralTypeOf!( Q!T )));
5854 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5857 static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5858 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5859 static foreach (Q; TypeQualifierList)
5861 static assert(!is(IntegralTypeOf!( Q!T )));
5862 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5868 template FloatingPointTypeOf(T)
5870 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5871 alias X = FloatingPointTypeOf!AT;
5872 else
5873 alias X = OriginalType!T;
5875 static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5877 alias FloatingPointTypeOf = X;
5879 else
5880 static assert(0, T.stringof~" is not a floating point type");
5883 @safe unittest
5885 static foreach (T; FloatingPointTypeList)
5886 static foreach (Q; TypeQualifierList)
5888 static assert( is(Q!T == FloatingPointTypeOf!( Q!T )));
5889 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5892 static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5893 static foreach (Q; TypeQualifierList)
5895 static assert(!is(FloatingPointTypeOf!( Q!T )));
5896 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5902 template NumericTypeOf(T)
5904 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5906 alias NumericTypeOf = X;
5908 else
5909 static assert(0, T.stringof~" is not a numeric type");
5912 @safe unittest
5914 static foreach (T; NumericTypeList)
5915 static foreach (Q; TypeQualifierList)
5917 static assert( is(Q!T == NumericTypeOf!( Q!T )));
5918 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5921 static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5922 static foreach (Q; TypeQualifierList)
5924 static assert(!is(NumericTypeOf!( Q!T )));
5925 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5931 template UnsignedTypeOf(T)
5933 static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5934 alias UnsignedTypeOf = X;
5935 else
5936 static assert(0, T.stringof~" is not an unsigned type.");
5941 template SignedTypeOf(T)
5943 static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5944 alias SignedTypeOf = X;
5945 else static if (is(FloatingPointTypeOf!T X))
5946 alias SignedTypeOf = X;
5947 else
5948 static assert(0, T.stringof~" is not an signed type.");
5953 template CharTypeOf(T)
5955 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5956 alias X = CharTypeOf!AT;
5957 else
5958 alias X = OriginalType!T;
5960 static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5962 alias CharTypeOf = X;
5964 else
5965 static assert(0, T.stringof~" is not a character type");
5968 @safe unittest
5970 static foreach (T; CharTypeList)
5971 static foreach (Q; TypeQualifierList)
5973 static assert( is(CharTypeOf!( Q!T )));
5974 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5977 static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5978 static foreach (Q; TypeQualifierList)
5980 static assert(!is(CharTypeOf!( Q!T )));
5981 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5984 static foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5985 static foreach (Q; TypeQualifierList)
5987 static assert(!is(CharTypeOf!( Q!T )));
5988 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5994 template StaticArrayTypeOf(T)
5996 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5997 alias X = StaticArrayTypeOf!AT;
5998 else
5999 alias X = OriginalType!T;
6001 static if (__traits(isStaticArray, X))
6002 alias StaticArrayTypeOf = X;
6003 else
6004 static assert(0, T.stringof~" is not a static array type");
6007 @safe unittest
6009 static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6010 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6012 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) ));
6014 static foreach (P; TypeQualifierList)
6015 { // SubTypeOf cannot have inout type
6016 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
6020 static foreach (T; AliasSeq!void)
6021 static foreach (Q; AliasSeq!TypeQualifierList)
6023 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
6029 template DynamicArrayTypeOf(T)
6031 import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
6032 alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
6035 @safe unittest
6037 import std.meta : Alias;
6038 static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6039 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6041 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) ));
6042 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) ));
6044 static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
6046 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
6047 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
6051 static assert(!is(DynamicArrayTypeOf!(int[3])));
6052 static assert(!is(DynamicArrayTypeOf!(void[3])));
6053 static assert(!is(DynamicArrayTypeOf!(typeof(null))));
6058 template ArrayTypeOf(T)
6060 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
6062 alias ArrayTypeOf = X;
6064 else
6065 static assert(0, T.stringof~" is not an array type");
6069 * Converts strings and string-like types to the corresponding dynamic array of characters.
6070 * Params:
6071 * T = one of the following:
6072 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6073 * (`shared` is rejected)
6074 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6075 * (`shared` is rejected)
6076 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6078 * Other cases are rejected with a compile time error.
6079 * `typeof(null)` is rejected.
6081 * Returns:
6082 * The result of `[]` applied to the qualified character type.
6084 template StringTypeOf(T)
6086 static if (is(T == typeof(null)))
6088 // It is impossible to determine exact string type from typeof(null) -
6089 // it means that StringTypeOf!(typeof(null)) is undefined.
6090 // Then this behavior is convenient for template constraint.
6091 static assert(0, T.stringof~" is not a string type");
6093 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
6095 static if (is(T : U[], U))
6096 alias StringTypeOf = U[];
6097 else
6098 static assert(0);
6100 else
6101 static assert(0, T.stringof~" is not a string type");
6104 @safe unittest
6106 import std.meta : Alias;
6107 static foreach (T; CharTypeList)
6108 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6110 static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6112 static if (!__traits(isSame, Q, InoutOf))
6114 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6116 alias Str = Q!T[];
6117 struct C(S) { S val; alias val this; }
6118 static assert(is(StringTypeOf!(C!Str) == Str));
6122 static foreach (T; CharTypeList)
6123 static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6125 static assert(!is(StringTypeOf!( Q!T[] )));
6129 @safe unittest
6131 static assert(is(StringTypeOf!(char[4]) == char[]));
6133 struct S
6135 string s;
6136 alias s this;
6139 struct T
6141 S s;
6142 alias s this;
6145 static assert(is(StringTypeOf!S == string));
6146 static assert(is(StringTypeOf!T == string));
6151 template AssocArrayTypeOf(T)
6153 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6154 alias X = AssocArrayTypeOf!AT;
6155 else
6156 alias X = OriginalType!T;
6158 static if (__traits(isAssociativeArray, X))
6160 alias AssocArrayTypeOf = X;
6162 else
6163 static assert(0, T.stringof~" is not an associative array type");
6166 @safe unittest
6168 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6169 static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6170 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6171 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6173 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) ));
6176 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6177 static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6178 static foreach (P; AliasSeq!TypeQualifierList)
6179 static foreach (Q; AliasSeq!TypeQualifierList)
6180 static foreach (R; AliasSeq!TypeQualifierList)
6182 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6188 template BuiltinTypeOf(T)
6190 static if (is(T : void))
6191 alias BuiltinTypeOf = void;
6192 else
6194 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6195 alias X = BuiltinTypeOf!AT;
6196 else
6197 alias X = OriginalType!T;
6198 static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6199 __traits(isStaticArray, X) || is(X == E[], E) ||
6200 __traits(isAssociativeArray, X) || is(X == typeof(null)))
6201 alias BuiltinTypeOf = X;
6202 else
6203 static assert(0);
6207 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6208 // isSomething
6209 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6212 * Detect whether `T` is a built-in boolean type or enum of boolean base type.
6214 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6217 @safe unittest
6219 static assert( isBoolean!bool);
6220 enum EB : bool { a = true }
6221 static assert( isBoolean!EB);
6223 struct SubTypeOfBool
6225 bool val;
6226 alias val this;
6228 static assert(!isBoolean!(SubTypeOfBool));
6231 @safe unittest
6233 static struct S(T)
6235 T t;
6236 alias t this;
6238 static assert(!isIntegral!(S!bool));
6242 * Detect whether `T` is a built-in integral type.
6243 * Integral types are `byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`,
6244 * and enums with an integral type as its base type.
6245 * Params:
6246 * T = type to test
6247 * Returns:
6248 * `true` if `T` is an integral type
6249 * Note:
6250 * this is not the same as $(LINK2 https://dlang.org/spec/traits.html#isIntegral, `__traits(isIntegral)`)
6252 template isIntegral(T)
6254 static if (!__traits(isIntegral, T))
6255 enum isIntegral = false;
6256 else static if (is(T U == enum))
6257 enum isIntegral = isIntegral!U;
6258 else
6259 enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6260 && !is(immutable T == immutable bool) && !is(T == __vector);
6264 @safe unittest
6266 static assert(
6267 isIntegral!byte &&
6268 isIntegral!short &&
6269 isIntegral!int &&
6270 isIntegral!long &&
6271 isIntegral!(const(long)) &&
6272 isIntegral!(immutable(long))
6275 static assert(
6276 !isIntegral!bool &&
6277 !isIntegral!char &&
6278 !isIntegral!double
6281 // types which act as integral values do not pass
6282 struct S
6284 int val;
6285 alias val this;
6288 static assert(!isIntegral!S);
6291 @safe unittest
6293 static foreach (T; IntegralTypeList)
6295 static foreach (Q; TypeQualifierList)
6297 static assert( isIntegral!(Q!T));
6298 static assert(!isIntegral!(SubTypeOf!(Q!T)));
6302 static assert(!isIntegral!float);
6304 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
6305 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6306 enum EI : int { a = -1, b = 0, c = 1 }
6307 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU);
6308 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI);
6312 * Detect whether `T` is a built-in floating point type.
6314 * See also: $(DDSUBLINK spec/traits, isFloating, `__traits(isFloating, T)`)
6316 // is(T : real) to discount complex types
6317 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6320 @safe unittest
6322 static assert(
6323 isFloatingPoint!float &&
6324 isFloatingPoint!double &&
6325 isFloatingPoint!real &&
6326 isFloatingPoint!(const(real)) &&
6327 isFloatingPoint!(immutable(real))
6330 static assert(!isFloatingPoint!int);
6332 // types which act as floating point values do not pass
6333 struct S
6335 float val;
6336 alias val this;
6339 static assert(!isFloatingPoint!S);
6342 @safe unittest
6344 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6346 static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6348 static foreach (Q; TypeQualifierList)
6350 static assert( isFloatingPoint!(Q!T));
6351 static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6354 static foreach (T; IntegralTypeList)
6356 static foreach (Q; TypeQualifierList)
6358 static assert(!isFloatingPoint!(Q!T));
6361 static if (is(__vector(float[4])))
6363 static assert(!isFloatingPoint!(__vector(float[4])));
6368 * Detect whether `T` is a built-in numeric type (integral or floating
6369 * point).
6371 template isNumeric(T)
6373 static if (!__traits(isArithmetic, T))
6374 enum isNumeric = false;
6375 else static if (__traits(isFloating, T))
6376 enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6377 else static if (is(T U == enum))
6378 enum isNumeric = isNumeric!U;
6379 else
6380 enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6381 && !is(immutable T == immutable bool) && !is(T == __vector);
6385 @safe unittest
6387 static assert(
6388 isNumeric!byte &&
6389 isNumeric!short &&
6390 isNumeric!int &&
6391 isNumeric!long &&
6392 isNumeric!float &&
6393 isNumeric!double &&
6394 isNumeric!real &&
6395 isNumeric!(const(real)) &&
6396 isNumeric!(immutable(real))
6399 static assert(
6400 !isNumeric!void &&
6401 !isNumeric!bool &&
6402 !isNumeric!char &&
6403 !isNumeric!wchar &&
6404 !isNumeric!dchar
6407 // types which act as numeric values do not pass
6408 struct S
6410 int val;
6411 alias val this;
6414 static assert(!isNumeric!S);
6417 @safe unittest
6419 static foreach (T; AliasSeq!(NumericTypeList))
6421 static foreach (Q; TypeQualifierList)
6423 static assert( isNumeric!(Q!T));
6424 static assert(!isNumeric!(SubTypeOf!(Q!T)));
6428 static struct S(T)
6430 T t;
6431 alias t this;
6433 static assert(!isNumeric!(S!int));
6435 enum EChar : char { a = 0, }
6436 static assert(!isNumeric!EChar);
6438 static if (is(__vector(float[4])))
6440 static assert(!isNumeric!(__vector(float[4])));
6442 static if (is(__vector(int[4])))
6444 static assert(!isNumeric!(__vector(int[4])));
6447 static assert(!isNumeric!ifloat);
6448 static assert(!isNumeric!cfloat);
6452 * Detect whether `T` is a scalar type (a built-in numeric, character or
6453 * boolean type).
6455 * See also: $(DDSUBLINK spec/traits, isScalar, `__traits(isScalar, T)`)
6457 // is(T : real) to discount complex types
6458 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6461 @safe unittest
6463 static assert(!isScalarType!void);
6464 static assert( isScalarType!(immutable(byte)));
6465 static assert( isScalarType!(immutable(ushort)));
6466 static assert( isScalarType!(immutable(int)));
6467 static assert( isScalarType!(ulong));
6468 static assert( isScalarType!(shared(float)));
6469 static assert( isScalarType!(shared(const bool)));
6470 static assert( isScalarType!(const(char)));
6471 static assert( isScalarType!(wchar));
6472 static assert( isScalarType!(const(dchar)));
6473 static assert( isScalarType!(const(double)));
6474 static assert( isScalarType!(const(real)));
6477 @safe unittest
6479 static struct S(T)
6481 T t;
6482 alias t this;
6484 static assert(!isScalarType!(S!int));
6488 * Detect whether `T` is a basic type (scalar type or void).
6490 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6493 @safe unittest
6495 static assert(isBasicType!void);
6496 static assert(isBasicType!(const(void)));
6497 static assert(isBasicType!(shared(void)));
6498 static assert(isBasicType!(immutable(void)));
6499 static assert(isBasicType!(shared const(void)));
6500 static assert(isBasicType!(shared inout(void)));
6501 static assert(isBasicType!(shared inout const(void)));
6502 static assert(isBasicType!(inout(void)));
6503 static assert(isBasicType!(inout const(void)));
6504 static assert(isBasicType!(immutable(int)));
6505 static assert(isBasicType!(shared(float)));
6506 static assert(isBasicType!(shared(const bool)));
6507 static assert(isBasicType!(const(dchar)));
6511 * Detect whether `T` is a built-in unsigned numeric type.
6513 template isUnsigned(T)
6515 static if (!__traits(isUnsigned, T))
6516 enum isUnsigned = false;
6517 else static if (is(T U == enum))
6518 enum isUnsigned = isUnsigned!U;
6519 else
6520 enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6521 && !is(immutable T == immutable bool) && !is(T == __vector);
6525 @safe unittest
6527 static assert(
6528 isUnsigned!uint &&
6529 isUnsigned!ulong
6532 static assert(
6533 !isUnsigned!char &&
6534 !isUnsigned!int &&
6535 !isUnsigned!long &&
6536 !isUnsigned!char &&
6537 !isUnsigned!wchar &&
6538 !isUnsigned!dchar
6542 @safe unittest
6544 static foreach (T; AliasSeq!(UnsignedIntTypeList))
6546 static foreach (Q; TypeQualifierList)
6548 static assert( isUnsigned!(Q!T));
6549 static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6553 static struct S(T)
6555 T t;
6556 alias t this;
6558 static assert(!isUnsigned!(S!uint));
6560 enum EChar : char { a = 0, }
6561 static assert(!isUnsigned!EChar);
6563 static if (is(__vector(uint[4])))
6565 static assert(!isUnsigned!(__vector(uint[4])));
6570 * Detect whether `T` is a built-in signed numeric type.
6572 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6573 && is(T : real);
6576 @safe unittest
6578 static assert(
6579 isSigned!int &&
6580 isSigned!long
6583 static assert(
6584 !isSigned!uint &&
6585 !isSigned!ulong
6589 @safe unittest
6591 enum E { e1 = 0 }
6592 static assert(isSigned!E);
6594 enum Eubyte : ubyte { e1 = 0 }
6595 static assert(!isSigned!Eubyte);
6597 static foreach (T; AliasSeq!(SignedIntTypeList))
6599 static foreach (Q; TypeQualifierList)
6601 static assert( isSigned!(Q!T));
6602 static assert(!isSigned!(SubTypeOf!(Q!T)));
6606 static struct S(T)
6608 T t;
6609 alias t this;
6611 static assert(!isSigned!(S!uint));
6613 static if (is(__vector(int[4])))
6615 static assert(!isSigned!(__vector(int[4])));
6618 static assert(!isSigned!ifloat);
6619 static assert(!isSigned!cfloat);
6622 // https://issues.dlang.org/show_bug.cgi?id=17196
6623 @safe unittest
6625 static assert(isUnsigned!bool == false);
6626 static assert(isSigned!bool == false);
6630 * Detect whether `T` is one of the built-in character types.
6632 * The built-in char types are any of `char`, `wchar` or `dchar`, with
6633 * or without qualifiers.
6635 template isSomeChar(T)
6637 static if (!__traits(isUnsigned, T))
6638 enum isSomeChar = false;
6639 else static if (is(T U == enum))
6640 enum isSomeChar = isSomeChar!U;
6641 else
6642 enum isSomeChar = !__traits(isZeroInit, T);
6646 @safe unittest
6648 //Char types
6649 static assert( isSomeChar!char);
6650 static assert( isSomeChar!wchar);
6651 static assert( isSomeChar!dchar);
6652 static assert( isSomeChar!(typeof('c')));
6653 static assert( isSomeChar!(immutable char));
6654 static assert( isSomeChar!(const dchar));
6656 //Non char types
6657 static assert(!isSomeChar!int);
6658 static assert(!isSomeChar!byte);
6659 static assert(!isSomeChar!string);
6660 static assert(!isSomeChar!wstring);
6661 static assert(!isSomeChar!dstring);
6662 static assert(!isSomeChar!(char[4]));
6665 @safe unittest
6667 enum EC : char { a = 'x', b = 'y' }
6669 static foreach (T; AliasSeq!(CharTypeList, EC))
6671 static foreach (Q; TypeQualifierList)
6673 static assert( isSomeChar!( Q!T ));
6674 static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6678 // alias-this types are not allowed
6679 static struct S(T)
6681 T t;
6682 alias t this;
6684 static assert(!isSomeChar!(S!char));
6688 Detect whether `T` is one of the built-in string types.
6690 The built-in string types are `Char[]`, where `Char` is any of `char`,
6691 `wchar` or `dchar`, with or without qualifiers.
6693 Static arrays of characters (like `char[80]`) are not considered
6694 built-in string types.
6696 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6699 @safe unittest
6701 //String types
6702 static assert( isSomeString!string);
6703 static assert( isSomeString!(wchar[]));
6704 static assert( isSomeString!(dchar[]));
6705 static assert( isSomeString!(typeof("aaa")));
6706 static assert( isSomeString!(const(char)[]));
6708 //Non string types
6709 static assert(!isSomeString!int);
6710 static assert(!isSomeString!(int[]));
6711 static assert(!isSomeString!(byte[]));
6712 static assert(!isSomeString!(typeof(null)));
6713 static assert(!isSomeString!(char[4]));
6715 enum ES : string { a = "aaa", b = "bbb" }
6716 static assert(!isSomeString!ES);
6718 static struct Stringish
6720 string str;
6721 alias str this;
6723 static assert(!isSomeString!Stringish);
6726 @safe unittest
6728 static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6730 static assert( isSomeString!( T ));
6731 static assert(!isSomeString!(SubTypeOf!(T)));
6733 enum C : char { _ = 0 }
6734 static assert(!isSomeString!(C[]));
6738 * Detect whether type `T` is a narrow string.
6740 * All arrays that use char, wchar, and their qualified versions are narrow
6741 * strings. (Those include string and wstring).
6743 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6746 @safe unittest
6748 static assert(isNarrowString!string);
6749 static assert(isNarrowString!wstring);
6750 static assert(isNarrowString!(char[]));
6751 static assert(isNarrowString!(wchar[]));
6753 static assert(!isNarrowString!dstring);
6754 static assert(!isNarrowString!(dchar[]));
6756 static assert(!isNarrowString!(typeof(null)));
6757 static assert(!isNarrowString!(char[4]));
6759 enum ES : string { a = "aaa", b = "bbb" }
6760 static assert(!isNarrowString!ES);
6762 static struct Stringish
6764 string str;
6765 alias str this;
6767 static assert(!isNarrowString!Stringish);
6770 @safe unittest
6772 import std.meta : Alias;
6773 static foreach (T; AliasSeq!(char[], string, wstring))
6775 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6777 static assert( isNarrowString!( Q!T ));
6778 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6782 static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6784 static foreach (Q; TypeQualifierList)
6786 static assert(!isNarrowString!( Q!T ));
6787 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6790 enum C : char { _ = 0 }
6791 static assert(!isNarrowString!(C[]));
6795 * Detects whether `T` is a comparable type. Basic types and structs and
6796 * classes that implement opCmp are ordering comparable.
6798 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6801 @safe unittest
6803 static assert(isOrderingComparable!int);
6804 static assert(isOrderingComparable!string);
6806 static struct Foo {}
6807 static assert(!isOrderingComparable!Foo);
6809 static struct Bar
6811 int a;
6812 auto opCmp(Bar b1) const { return a - b1.a; }
6815 Bar b1 = Bar(5);
6816 Bar b2 = Bar(7);
6817 assert(isOrderingComparable!Bar && b2 > b1);
6820 /// ditto
6821 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6823 @safe unittest
6825 static assert(isEqualityComparable!int);
6826 static assert(isEqualityComparable!string);
6827 static assert(!isEqualityComparable!void);
6829 struct Foo {}
6830 static assert(isEqualityComparable!Foo);
6832 struct Bar
6834 int a;
6835 auto opEquals(Bar b1) const { return a == b1.a; }
6838 Bar b1 = Bar(5);
6839 Bar b2 = Bar(5);
6840 Bar b3 = Bar(7);
6841 static assert(isEqualityComparable!Bar);
6842 assert(b1 == b2);
6843 assert(b1 != b3);
6847 $(RED Warning: This trait will be deprecated as soon as it is no longer used
6848 in Phobos. For a function parameter to safely accept a type
6849 that implicitly converts to string as a string, the conversion
6850 needs to happen at the callsite; otherwise, the conversion is
6851 done inside the function, and in many cases, that means that
6852 local memory is sliced (e.g. if a static array is passed to
6853 the function, then it's copied, and the resulting dynamic
6854 array will be a slice of a local variable). So, if the
6855 resulting string escapes the function, the string refers to
6856 invalid memory, and accessing it would mean accessing invalid
6857 memory. As such, the only safe way for a function to accept
6858 types that implicitly convert to string is for the implicit
6859 conversion to be done at the callsite, and that can only occur
6860 if the parameter is explicitly typed as an array, whereas
6861 using isConvertibleToString in a template constraint would
6862 result in the conversion being done inside the function. As
6863 such, isConvertibleToString is inherently unsafe and is going
6864 to be deprecated.)
6866 Detect whether `T` is a struct, static array, or enum that is implicitly
6867 convertible to a string.
6869 template isConvertibleToString(T)
6871 enum isConvertibleToString =
6872 (isAggregateType!T || isStaticArray!T || is(T == enum))
6873 && is(StringTypeOf!T);
6877 @safe unittest
6879 static struct AliasedString
6881 string s;
6882 alias s this;
6885 enum StringEnum { a = "foo" }
6887 assert(!isConvertibleToString!string);
6888 assert(isConvertibleToString!AliasedString);
6889 assert(isConvertibleToString!StringEnum);
6890 assert(isConvertibleToString!(char[25]));
6891 assert(!isConvertibleToString!(char[]));
6894 // https://issues.dlang.org/show_bug.cgi?id=16573
6895 @safe unittest
6897 enum I : int { foo = 1 }
6898 enum S : string { foo = "foo" }
6899 assert(!isConvertibleToString!I);
6900 assert(isConvertibleToString!S);
6903 package template convertToString(T)
6905 static if (isConvertibleToString!T)
6906 alias convertToString = StringTypeOf!T;
6907 else
6908 alias convertToString = T;
6912 * Detect whether type `T` is a string that will be autodecoded.
6914 * Given a type `S` that is one of:
6915 * $(OL
6916 * $(LI `const(char)[]`)
6917 * $(LI `const(wchar)[]`)
6919 * Type `T` can be one of:
6920 * $(OL
6921 * $(LI `S`)
6922 * $(LI implicitly convertible to `T`)
6923 * $(LI an enum with a base type `T`)
6924 * $(LI an aggregate with a base type `T`)
6926 * with the proviso that `T` cannot be a static array.
6928 * Params:
6929 * T = type to be tested
6931 * Returns:
6932 * true if T represents a string that is subject to autodecoding
6934 * See Also:
6935 * $(LREF isNarrowString)
6937 template isAutodecodableString(T)
6939 import std.range.primitives : autodecodeStrings;
6941 enum isAutodecodableString = autodecodeStrings &&
6942 (is(T : const char[]) || is(T : const wchar[]))
6943 && !is(T : U[n], U, size_t n)
6944 && !is(immutable T : immutable noreturn[]);
6948 @safe unittest
6950 static struct Stringish
6952 string s;
6953 alias s this;
6955 static assert(isAutodecodableString!wstring);
6956 static assert(isAutodecodableString!Stringish);
6957 static assert(!isAutodecodableString!dstring);
6959 enum E : const(char)[3] { X = "abc" }
6960 enum F : const(char)[] { X = "abc" }
6961 enum G : F { X = F.init }
6963 static assert(isAutodecodableString!(char[]));
6964 static assert(!isAutodecodableString!(E));
6965 static assert(isAutodecodableString!(F));
6966 static assert(isAutodecodableString!(G));
6968 struct Stringish2
6970 Stringish s;
6971 alias s this;
6974 enum H : Stringish { X = Stringish() }
6975 enum I : Stringish2 { X = Stringish2() }
6977 static assert(isAutodecodableString!(H));
6978 static assert(isAutodecodableString!(I));
6980 static assert(!isAutodecodableString!(noreturn[]));
6981 static assert(!isAutodecodableString!(immutable(noreturn)[]));
6985 * Detect whether type `T` is a static array.
6987 * See also: $(DDSUBLINK spec/traits, isStaticArray, `__traits(isStaticArray, T)`)
6989 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6992 @safe unittest
6994 static assert( isStaticArray!(int[3]));
6995 static assert( isStaticArray!(const(int)[5]));
6996 static assert( isStaticArray!(const(int)[][5]));
6998 static assert(!isStaticArray!(const(int)[]));
6999 static assert(!isStaticArray!(immutable(int)[]));
7000 static assert(!isStaticArray!(const(int)[4][]));
7001 static assert(!isStaticArray!(int[]));
7002 static assert(!isStaticArray!(int[char]));
7003 static assert(!isStaticArray!(int[1][]));
7004 static assert(!isStaticArray!(int[int]));
7005 static assert(!isStaticArray!int);
7008 @safe unittest
7010 static foreach (T; AliasSeq!(int[51], int[][2],
7011 char[][int][11], immutable char[13u],
7012 const(real)[1], const(real)[1][1], void[0]))
7014 static foreach (Q; TypeQualifierList)
7016 static assert( isStaticArray!( Q!T ));
7017 static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
7021 //enum ESA : int[1] { a = [1], b = [2] }
7022 //static assert( isStaticArray!ESA);
7026 * Detect whether type `T` is a dynamic array.
7028 template isDynamicArray(T)
7030 static if (is(T == U[], U))
7031 enum bool isDynamicArray = true;
7032 else static if (is(T U == enum))
7033 // BUG: isDynamicArray / isStaticArray considers enums
7034 // with appropriate base types as dynamic/static arrays
7035 // Retain old behaviour for now, see
7036 // https://github.com/dlang/phobos/pull/7574
7037 enum bool isDynamicArray = isDynamicArray!U;
7038 else
7039 enum bool isDynamicArray = false;
7043 @safe unittest
7045 static assert( isDynamicArray!(int[]));
7046 static assert( isDynamicArray!(string));
7047 static assert( isDynamicArray!(long[3][]));
7049 static assert(!isDynamicArray!(int[5]));
7050 static assert(!isDynamicArray!(typeof(null)));
7053 @safe unittest
7055 import std.meta : AliasSeq;
7056 static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
7058 static foreach (Q; TypeQualifierList)
7060 static assert( isDynamicArray!( Q!T ));
7061 static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
7065 static assert(!isDynamicArray!(int[5]));
7067 static struct AliasThis
7069 int[] values;
7070 alias values this;
7073 static assert(!isDynamicArray!AliasThis);
7075 // https://github.com/dlang/phobos/pull/7574/files#r464115492
7076 enum E : string
7078 a = "a",
7079 b = "b",
7081 static assert( isDynamicArray!E);
7085 * Detect whether type `T` is an array (static or dynamic; for associative
7086 * arrays see $(LREF isAssociativeArray)).
7088 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
7091 @safe unittest
7093 static assert( isArray!(int[]));
7094 static assert( isArray!(int[5]));
7095 static assert( isArray!(string));
7097 static assert(!isArray!uint);
7098 static assert(!isArray!(uint[uint]));
7099 static assert(!isArray!(typeof(null)));
7102 @safe unittest
7104 import std.meta : AliasSeq;
7105 static foreach (T; AliasSeq!(int[], int[5], void[]))
7107 static foreach (Q; TypeQualifierList)
7109 static assert( isArray!(Q!T));
7110 static assert(!isArray!(SubTypeOf!(Q!T)));
7116 * Detect whether `T` is an associative array type
7118 * See also: $(DDSUBLINK spec/traits, isAssociativeArray, `__traits(isAssociativeArray, T)`)
7120 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
7123 @safe unittest
7125 struct S;
7127 static assert( isAssociativeArray!(int[string]));
7128 static assert( isAssociativeArray!(S[S]));
7129 static assert(!isAssociativeArray!(string[]));
7130 static assert(!isAssociativeArray!S);
7131 static assert(!isAssociativeArray!(int[4]));
7134 @safe unittest
7136 struct Foo
7138 @property uint[] keys() { return null; }
7139 @property uint[] values() { return null; }
7142 static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7144 static foreach (Q; TypeQualifierList)
7146 static assert( isAssociativeArray!(Q!T));
7147 static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7151 static assert(!isAssociativeArray!Foo);
7152 static assert(!isAssociativeArray!int);
7153 static assert(!isAssociativeArray!(int[]));
7154 static assert(!isAssociativeArray!(typeof(null)));
7156 //enum EAA : int[int] { a = [1:1], b = [2:2] }
7157 //static assert( isAssociativeArray!EAA);
7161 * Detect whether type `T` is a builtin type.
7163 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7166 @safe unittest
7168 class C;
7169 union U;
7170 struct S;
7171 interface I;
7173 static assert( isBuiltinType!void);
7174 static assert( isBuiltinType!string);
7175 static assert( isBuiltinType!(int[]));
7176 static assert( isBuiltinType!(C[string]));
7177 static assert( isBuiltinType!(typeof(null)));
7178 static assert(!isBuiltinType!C);
7179 static assert(!isBuiltinType!U);
7180 static assert(!isBuiltinType!S);
7181 static assert(!isBuiltinType!I);
7182 static assert(!isBuiltinType!(void delegate(int)));
7186 * Detect whether type `T` is a SIMD vector type.
7188 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7191 @safe unittest
7193 static if (is(__vector(float[4])))
7195 alias SimdVec = __vector(float[4]);
7196 static assert(isSIMDVector!(__vector(float[4])));
7197 static assert(isSIMDVector!SimdVec);
7199 static assert(!isSIMDVector!uint);
7200 static assert(!isSIMDVector!(float[4]));
7204 * Detect whether type `T` is a pointer.
7206 enum bool isPointer(T) = is(T == U*, U);
7209 @safe unittest
7211 void fun();
7213 static assert( isPointer!(int*));
7214 static assert( isPointer!(int function()));
7215 static assert(!isPointer!int);
7216 static assert(!isPointer!string);
7217 static assert(!isPointer!(typeof(null)));
7218 static assert(!isPointer!(typeof(fun)));
7219 static assert(!isPointer!(int delegate()));
7222 @safe unittest
7224 static foreach (T; AliasSeq!(int*, void*, char[]*))
7226 static foreach (Q; TypeQualifierList)
7228 static assert( isPointer!(Q!T));
7229 static assert(!isPointer!(SubTypeOf!(Q!T)));
7233 static assert(!isPointer!uint);
7234 static assert(!isPointer!(uint[uint]));
7235 static assert(!isPointer!(char[]));
7236 static assert(!isPointer!(typeof(null)));
7240 Returns the target type of a pointer.
7242 alias PointerTarget(T : T*) = T;
7245 @safe unittest
7247 static assert(is(PointerTarget!(int*) == int));
7248 static assert(is(PointerTarget!(void*) == void));
7252 * Detect whether type `T` is an aggregate type.
7254 template isAggregateType(T)
7256 static if (is(T == enum))
7257 enum isAggregateType = isAggregateType!(OriginalType!T);
7258 else
7259 enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union);
7263 @safe unittest
7265 class C {}
7266 union U {}
7267 struct S {}
7268 interface I {}
7270 static assert( isAggregateType!C);
7271 static assert( isAggregateType!U);
7272 static assert( isAggregateType!S);
7273 static assert( isAggregateType!I);
7274 static assert(!isAggregateType!void);
7275 static assert(!isAggregateType!string);
7276 static assert(!isAggregateType!(int[]));
7277 static assert(!isAggregateType!(C[string]));
7278 static assert(!isAggregateType!(void delegate(int)));
7280 enum ES : S { a = S.init }
7281 enum EC : C { a = C.init }
7282 enum EI : I { a = I.init }
7283 enum EU : U { a = U.init }
7285 static assert( isAggregateType!ES);
7286 static assert( isAggregateType!EC);
7287 static assert( isAggregateType!EI);
7288 static assert( isAggregateType!EU);
7292 * Returns `true` if T can be iterated over using a `foreach` loop with
7293 * a single loop variable of automatically inferred type, regardless of how
7294 * the `foreach` loop is implemented. This includes ranges, structs/classes
7295 * that define `opApply` with a single loop variable, and builtin dynamic,
7296 * static and associative arrays.
7298 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7301 @safe unittest
7303 struct OpApply
7305 int opApply(scope int delegate(ref uint) dg) { assert(0); }
7308 struct Range
7310 @property uint front() { assert(0); }
7311 void popFront() { assert(0); }
7312 enum bool empty = false;
7315 static assert( isIterable!(uint[]));
7316 static assert( isIterable!OpApply);
7317 static assert( isIterable!(uint[string]));
7318 static assert( isIterable!Range);
7320 static assert(!isIterable!uint);
7324 * Returns true if T is not const or immutable. Note that isMutable is true for
7325 * string, or immutable(char)[], because the 'head' is mutable.
7327 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7330 @safe unittest
7332 static assert( isMutable!int);
7333 static assert( isMutable!string);
7334 static assert( isMutable!(shared int));
7335 static assert( isMutable!(shared const(int)[]));
7337 static assert(!isMutable!(const int));
7338 static assert(!isMutable!(inout int));
7339 static assert(!isMutable!(shared(const int)));
7340 static assert(!isMutable!(shared(inout int)));
7341 static assert(!isMutable!(immutable string));
7345 * Returns true if T is an instance of the template S.
7347 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7348 /// ditto
7349 template isInstanceOf(alias S, alias T)
7351 enum impl(alias T : S!Args, Args...) = true;
7352 enum impl(alias T) = false;
7353 enum isInstanceOf = impl!T;
7357 @safe unittest
7359 static struct Foo(T...) { }
7360 static struct Bar(T...) { }
7361 static struct Doo(T) { }
7362 static struct ABC(int x) { }
7363 static void fun(T)() { }
7364 template templ(T) { }
7366 static assert(isInstanceOf!(Foo, Foo!int));
7367 static assert(!isInstanceOf!(Foo, Bar!int));
7368 static assert(!isInstanceOf!(Foo, int));
7369 static assert(isInstanceOf!(Doo, Doo!int));
7370 static assert(isInstanceOf!(ABC, ABC!1));
7371 static assert(!isInstanceOf!(Foo, Foo));
7372 static assert(isInstanceOf!(fun, fun!int));
7373 static assert(isInstanceOf!(templ, templ!int));
7377 * To use `isInstanceOf` to check the identity of a template while inside of said
7378 * template, use $(LREF TemplateOf).
7380 @safe unittest
7382 static struct A(T = void)
7384 // doesn't work as expected, only accepts A when T = void
7385 void func(B)(B b)
7386 if (isInstanceOf!(A, B)) {}
7388 // correct behavior
7389 void method(B)(B b)
7390 if (isInstanceOf!(TemplateOf!(A), B)) {}
7393 A!(void) a1;
7394 A!(void) a2;
7395 A!(int) a3;
7397 static assert(!__traits(compiles, a1.func(a3)));
7398 static assert( __traits(compiles, a1.method(a2)));
7399 static assert( __traits(compiles, a1.method(a3)));
7402 @safe unittest
7404 static void fun1(T)() { }
7405 static void fun2(T)() { }
7406 template templ1(T) { }
7407 template templ2(T) { }
7409 static assert(!isInstanceOf!(fun1, fun2!int));
7410 static assert(!isInstanceOf!(templ1, templ2!int));
7414 * Check whether the tuple T is an expression tuple.
7415 * An expression tuple only contains expressions.
7417 * See_Also: $(LREF isTypeTuple).
7419 template isExpressions(T...)
7421 static foreach (Ti; T)
7423 static if (!is(typeof(isExpressions) == bool) && // not yet defined
7424 (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7426 enum isExpressions = false;
7429 static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7431 enum isExpressions = true;
7436 @safe unittest
7438 static assert(isExpressions!(1, 2.0, "a"));
7439 static assert(!isExpressions!(int, double, string));
7440 static assert(!isExpressions!(int, 2.0, "a"));
7444 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7447 alias isExpressionTuple = isExpressions;
7449 @safe unittest
7451 void foo();
7452 static int bar() { return 42; }
7453 immutable aa = [ 1: -1 ];
7454 alias myint = int;
7456 static assert( isExpressionTuple!(42));
7457 static assert( isExpressionTuple!aa);
7458 static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7459 static assert( isExpressionTuple!(bar()));
7461 static assert(!isExpressionTuple!isExpressionTuple);
7462 static assert(!isExpressionTuple!foo);
7463 static assert(!isExpressionTuple!( (a) { } ));
7464 static assert(!isExpressionTuple!int);
7465 static assert(!isExpressionTuple!myint);
7470 * Check whether the tuple `T` is a type tuple.
7471 * A type tuple only contains types.
7473 * See_Also: $(LREF isExpressions).
7475 enum isTypeTuple(T...) =
7477 static foreach (U; T)
7478 static if (!is(U))
7479 if (__ctfe)
7480 return false;
7481 return true;
7482 }();
7485 @safe unittest
7487 static assert(isTypeTuple!(int, float, string));
7488 static assert(!isTypeTuple!(1, 2.0, "a"));
7489 static assert(!isTypeTuple!(1, double, string));
7492 @safe unittest
7494 class C {}
7495 void func(int) {}
7496 auto c = new C;
7497 enum CONST = 42;
7499 static assert( isTypeTuple!int);
7500 static assert( isTypeTuple!string);
7501 static assert( isTypeTuple!C);
7502 static assert( isTypeTuple!(typeof(func)));
7503 static assert( isTypeTuple!(int, char, double));
7505 static assert(!isTypeTuple!c);
7506 static assert(!isTypeTuple!isTypeTuple);
7507 static assert(!isTypeTuple!CONST);
7512 Detect whether symbol or type `T` is a function pointer.
7514 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7517 @safe unittest
7519 static void foo() {}
7520 void bar() {}
7522 auto fpfoo = &foo;
7523 static assert( isFunctionPointer!fpfoo);
7524 static assert( isFunctionPointer!(void function()));
7526 auto dgbar = &bar;
7527 static assert(!isFunctionPointer!dgbar);
7528 static assert(!isFunctionPointer!(void delegate()));
7529 static assert(!isFunctionPointer!foo);
7530 static assert(!isFunctionPointer!bar);
7532 static assert( isFunctionPointer!((int a) {}));
7536 Detect whether symbol or type `T` is a delegate.
7538 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7541 @safe unittest
7543 static void sfunc() { }
7544 int x;
7545 void func() { x++; }
7547 int delegate() dg;
7548 assert(isDelegate!dg);
7549 assert(isDelegate!(int delegate()));
7550 assert(isDelegate!(typeof(&func)));
7552 int function() fp;
7553 assert(!isDelegate!fp);
7554 assert(!isDelegate!(int function()));
7555 assert(!isDelegate!(typeof(&sfunc)));
7559 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7561 Params:
7562 T = The type to check
7563 Returns:
7564 A `bool`
7566 enum bool isSomeFunction(alias T) =
7567 is(T == return) ||
7568 is(typeof(T) == return) ||
7569 is(typeof(&T) == return); // @property
7572 @safe unittest
7574 static real func(ref int) { return 0; }
7575 static void prop() @property { }
7576 class C
7578 real method(ref int) { return 0; }
7579 real prop() @property { return 0; }
7581 auto c = new C;
7582 auto fp = &func;
7583 auto dg = &c.method;
7585 static assert( isSomeFunction!func);
7586 static assert( isSomeFunction!prop);
7587 static assert( isSomeFunction!(C.method));
7588 static assert( isSomeFunction!(C.prop));
7589 static assert( isSomeFunction!(c.prop));
7590 static assert( isSomeFunction!fp);
7591 static assert( isSomeFunction!dg);
7593 real val;
7594 static assert(!isSomeFunction!int);
7595 static assert(!isSomeFunction!val);
7598 @safe unittest
7600 void nestedFunc() { }
7601 void nestedProp() @property { }
7602 static assert(isSomeFunction!nestedFunc);
7603 static assert(isSomeFunction!nestedProp);
7604 static assert(isSomeFunction!(real function(ref int)));
7605 static assert(isSomeFunction!(real delegate(ref int)));
7606 static assert(isSomeFunction!((int a) { return a; }));
7607 static assert(!isSomeFunction!isSomeFunction);
7611 Detect whether `T` is a callable object, which can be called with the
7612 function call operator `$(LPAREN)...$(RPAREN)`.
7614 template isCallable(alias callable)
7616 static if (is(typeof(&callable.opCall) == delegate))
7617 // T is a object which has a member function opCall().
7618 enum bool isCallable = true;
7619 else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7620 // T is a type which has a static member function opCall().
7621 enum bool isCallable = true;
7622 else static if (is(typeof(&callable.opCall!()) TemplateInstanceType))
7624 enum bool isCallable = isCallable!TemplateInstanceType;
7626 else static if (is(typeof(&callable!()) TemplateInstanceType))
7628 enum bool isCallable = isCallable!TemplateInstanceType;
7630 else
7632 enum bool isCallable = isSomeFunction!callable;
7636 /// Functions, lambdas, and aggregate types with (static) opCall.
7637 @safe unittest
7639 void f() { }
7640 int g(int x) { return x; }
7642 static assert( isCallable!f);
7643 static assert( isCallable!g);
7645 class C { int opCall(int) { return 0; } }
7646 auto c = new C;
7647 struct S { static int opCall(int) { return 0; } }
7648 interface I { real value() @property; }
7650 static assert( isCallable!c);
7651 static assert( isCallable!(c.opCall));
7652 static assert( isCallable!S);
7653 static assert( isCallable!(I.value));
7654 static assert( isCallable!((int a) { return a; }));
7656 static assert(!isCallable!I);
7659 /// Templates
7660 @safe unittest
7662 void f()() { }
7663 T g(T = int)(T x) { return x; }
7664 struct S1 { static void opCall()() { } }
7665 struct S2 { static T opCall(T = int)(T x) {return x; } }
7667 static assert( isCallable!f);
7668 static assert( isCallable!g);
7669 static assert( isCallable!S1);
7670 static assert( isCallable!S2);
7673 /// Overloaded functions and function templates.
7674 @safe unittest
7676 static struct Wrapper
7678 void f() { }
7679 int f(int x) { return x; }
7681 void g()() { }
7682 T g(T = int)(T x) { return x; }
7685 static assert(isCallable!(Wrapper.f));
7686 static assert(isCallable!(Wrapper.g));
7691 Detect whether `S` is an abstract function.
7693 See also: $(DDSUBLINK spec/traits, isAbstractFunction, `__traits(isAbstractFunction, S)`)
7694 Params:
7695 S = The symbol to check
7696 Returns:
7697 A `bool`
7699 enum isAbstractFunction(alias S) = __traits(isAbstractFunction, S);
7702 @safe unittest
7704 struct S { void foo() { } }
7705 class C { void foo() { } }
7706 class AC { abstract void foo(); }
7707 static assert(!isAbstractFunction!(int));
7708 static assert(!isAbstractFunction!(S.foo));
7709 static assert(!isAbstractFunction!(C.foo));
7710 static assert( isAbstractFunction!(AC.foo));
7714 * Detect whether `S` is a final function.
7716 * See also: $(DDSUBLINK spec/traits, isFinalFunction, `__traits(isFinalFunction, S)`)
7718 enum isFinalFunction(alias S) = __traits(isFinalFunction, S);
7721 @safe unittest
7723 struct S { void bar() { } }
7724 final class FC { void foo(); }
7725 class C
7727 void bar() { }
7728 final void foo();
7730 static assert(!isFinalFunction!(int));
7731 static assert(!isFinalFunction!(S.bar));
7732 static assert( isFinalFunction!(FC.foo));
7733 static assert(!isFinalFunction!(C.bar));
7734 static assert( isFinalFunction!(C.foo));
7738 Determines if `f` is a function that requires a context pointer.
7740 Params:
7741 f = The type to check
7742 Returns
7743 A `bool`
7745 template isNestedFunction(alias f)
7747 enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7751 @safe unittest
7753 static void f() {}
7754 static void fun()
7756 int i;
7757 int f() { return i; }
7759 static assert(isNestedFunction!(f));
7762 static assert(!isNestedFunction!f);
7765 // https://issues.dlang.org/show_bug.cgi?id=18669
7766 @safe unittest
7768 static class Outer
7770 class Inner
7774 int i;
7775 struct SS
7777 int bar() { return i; }
7779 static assert(!isNestedFunction!(Outer.Inner));
7780 static assert(!isNestedFunction!(SS));
7784 * Detect whether `S` is an abstract class.
7786 * See also: $(DDSUBLINK spec/traits, isAbstractClass, `__traits(isAbstractClass, S)`)
7788 enum isAbstractClass(alias S) = __traits(isAbstractClass, S);
7791 @safe unittest
7793 struct S { }
7794 class C { }
7795 abstract class AC { }
7796 static assert(!isAbstractClass!S);
7797 static assert(!isAbstractClass!C);
7798 static assert( isAbstractClass!AC);
7799 C c;
7800 static assert(!isAbstractClass!c);
7801 AC ac;
7802 static assert( isAbstractClass!ac);
7806 * Detect whether `S` is a final class.
7808 * See also: $(DDSUBLINK spec/traits, isFinalClass, `__traits(isFinalClass, S)`)
7810 enum isFinalClass(alias S) = __traits(isFinalClass, S);
7813 @safe unittest
7815 class C { }
7816 abstract class AC { }
7817 final class FC1 : C { }
7818 final class FC2 { }
7819 static assert(!isFinalClass!C);
7820 static assert(!isFinalClass!AC);
7821 static assert( isFinalClass!FC1);
7822 static assert( isFinalClass!FC2);
7823 C c;
7824 static assert(!isFinalClass!c);
7825 FC1 fc1;
7826 static assert( isFinalClass!fc1);
7829 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7830 // General Types
7831 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7833 version (StdDdoc)
7836 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7838 template Unconst(T)
7840 import core.internal.traits : CoreUnconst = Unconst;
7841 alias Unconst = CoreUnconst!(T);
7844 else
7846 import core.internal.traits : CoreUnconst = Unconst;
7847 alias Unconst = CoreUnconst;
7851 @safe unittest
7853 static assert(is(Unconst!int == int));
7854 static assert(is(Unconst!(const int) == int));
7855 static assert(is(Unconst!(immutable int) == int));
7856 static assert(is(Unconst!(shared int) == shared int));
7857 static assert(is(Unconst!(shared(const int)) == shared int));
7860 @safe unittest
7862 static assert(is(Unconst!( int) == int));
7863 static assert(is(Unconst!( const int) == int));
7864 static assert(is(Unconst!( inout int) == int));
7865 static assert(is(Unconst!( inout const int) == int));
7866 static assert(is(Unconst!(shared int) == shared int));
7867 static assert(is(Unconst!(shared const int) == shared int));
7868 static assert(is(Unconst!(shared inout int) == shared int));
7869 static assert(is(Unconst!(shared inout const int) == shared int));
7870 static assert(is(Unconst!( immutable int) == int));
7872 alias ImmIntArr = immutable(int[]);
7873 static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7877 Removes `shared` qualifier, if any, from type `T`.
7879 Note that while `immutable` is implicitly `shared`, it is unaffected by
7880 Unshared. Only explict `shared` is removed.
7882 template Unshared(T)
7884 static if (is(T == shared U, U))
7885 alias Unshared = U;
7886 else
7887 alias Unshared = T;
7891 @safe unittest
7893 static assert(is(Unshared!int == int));
7894 static assert(is(Unshared!(const int) == const int));
7895 static assert(is(Unshared!(immutable int) == immutable int));
7897 static assert(is(Unshared!(shared int) == int));
7898 static assert(is(Unshared!(shared(const int)) == const int));
7900 static assert(is(Unshared!(shared(int[])) == shared(int)[]));
7903 @safe unittest
7905 static assert(is(Unshared!( int) == int));
7906 static assert(is(Unshared!( const int) == const int));
7907 static assert(is(Unshared!( inout int) == inout int));
7908 static assert(is(Unshared!( inout const int) == inout const int));
7909 static assert(is(Unshared!(shared int) == int));
7910 static assert(is(Unshared!(shared const int) == const int));
7911 static assert(is(Unshared!(shared inout int) == inout int));
7912 static assert(is(Unshared!(shared inout const int) == inout const int));
7913 static assert(is(Unshared!( immutable int) == immutable int));
7916 version (StdDdoc)
7919 Removes all qualifiers, if any, from type `T`.
7921 template Unqual(T)
7923 import core.internal.traits : CoreUnqual = Unqual;
7924 alias Unqual = CoreUnqual!(T);
7927 else
7929 import core.internal.traits : CoreUnqual = Unqual;
7930 alias Unqual = CoreUnqual;
7934 @safe unittest
7936 static assert(is(Unqual!int == int));
7937 static assert(is(Unqual!(const int) == int));
7938 static assert(is(Unqual!(immutable int) == int));
7939 static assert(is(Unqual!(shared int) == int));
7940 static assert(is(Unqual!(shared(const int)) == int));
7943 @safe unittest
7945 static assert(is(Unqual!( int) == int));
7946 static assert(is(Unqual!( const int) == int));
7947 static assert(is(Unqual!( inout int) == int));
7948 static assert(is(Unqual!( inout const int) == int));
7949 static assert(is(Unqual!(shared int) == int));
7950 static assert(is(Unqual!(shared const int) == int));
7951 static assert(is(Unqual!(shared inout int) == int));
7952 static assert(is(Unqual!(shared inout const int) == int));
7953 static assert(is(Unqual!( immutable int) == int));
7955 alias ImmIntArr = immutable(int[]);
7956 static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7959 // [For internal use]
7960 package template ModifyTypePreservingTQ(alias Modifier, T)
7962 import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7963 alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7967 * Copies type qualifiers from `FromType` to `ToType`.
7969 * Supported type qualifiers:
7970 * $(UL
7971 * $(LI `const`)
7972 * $(LI `inout`)
7973 * $(LI `immutable`)
7974 * $(LI `shared`)
7977 template CopyTypeQualifiers(FromType, ToType)
7979 alias T(U) = ToType;
7980 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7984 @safe unittest
7986 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7989 @safe unittest
7991 static assert(is(CopyTypeQualifiers!( real, int) == int));
7992 static assert(is(CopyTypeQualifiers!( const real, int) == const int));
7993 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int));
7994 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int));
7995 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int));
7996 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int));
7997 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int));
7998 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
7999 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int));
8003 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
8004 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
8005 returned type will be the same as `ToType`.
8007 template CopyConstness(FromType, ToType)
8009 alias Unshared(T) = T;
8010 alias Unshared(T: shared U, U) = U;
8012 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
8016 @safe unittest
8018 const(int) i;
8019 CopyConstness!(typeof(i), float) f;
8020 assert( is(typeof(f) == const float));
8022 CopyConstness!(char, uint) u;
8023 assert( is(typeof(u) == uint));
8025 //The 'shared' qualifier will not be copied
8026 assert(!is(CopyConstness!(shared bool, int) == shared int));
8028 //But the constness will be
8029 assert( is(CopyConstness!(shared const real, double) == const double));
8031 //Careful, const(int)[] is a mutable array of const(int)
8032 alias MutT = CopyConstness!(const(int)[], int);
8033 assert(!is(MutT == const(int)));
8035 //Okay, const(int[]) applies to array and contained ints
8036 alias CstT = CopyConstness!(const(int[]), int);
8037 assert( is(CstT == const(int)));
8040 @safe unittest
8042 struct Test
8044 void method1() {}
8045 void method2() const {}
8046 void method3() immutable {}
8049 assert(is(CopyConstness!(typeof(Test.method1), real) == real));
8051 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
8053 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
8056 @safe unittest
8058 assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
8059 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
8062 @safe unittest
8064 static assert(is(CopyConstness!( int, real) == real));
8065 static assert(is(CopyConstness!(const int, real) == const real));
8066 static assert(is(CopyConstness!(inout int, real) == inout real));
8067 static assert(is(CopyConstness!(inout const int, real) == inout const real));
8068 static assert(is(CopyConstness!(shared int, real) == real));
8069 static assert(is(CopyConstness!(shared const int, real) == const real));
8070 static assert(is(CopyConstness!(shared inout int, real) == inout real));
8071 static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
8072 static assert(is(CopyConstness!(immutable int, real) == immutable real));
8076 Returns the inferred type of the loop variable when a variable of type T
8077 is iterated over using a `foreach` loop with a single loop variable and
8078 automatically inferred return type. Note that this may not be the same as
8079 `std.range.ElementType!Range` in the case of narrow strings, or if T
8080 has both opApply and a range interface.
8082 template ForeachType(T)
8084 alias ForeachType = typeof(
8085 (inout int x = 0)
8087 foreach (elem; T.init)
8089 return elem;
8091 assert(0);
8092 }());
8096 @safe unittest
8098 static assert(is(ForeachType!(uint[]) == uint));
8099 static assert(is(ForeachType!string == immutable(char)));
8100 static assert(is(ForeachType!(string[string]) == string));
8101 static assert(is(ForeachType!(inout(int)[]) == inout(int)));
8106 * Strips off all `enum`s from type `T`.
8108 template OriginalType(T)
8110 import core.internal.traits : _OriginalType = OriginalType;
8111 alias OriginalType = _OriginalType!T;
8115 @safe unittest
8117 enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
8118 enum F : E { a = E.a }
8119 alias G = const(F);
8120 static assert(is(OriginalType!E == real));
8121 static assert(is(OriginalType!F == real));
8122 static assert(is(OriginalType!G == const real));
8126 * Get the Key type of an Associative Array.
8128 alias KeyType(V : V[K], K) = K;
8131 @safe unittest
8133 alias Hash = int[string];
8134 static assert(is(KeyType!Hash == string));
8135 static assert(is(ValueType!Hash == int));
8136 KeyType!Hash str = "a"; // str is declared as string
8137 ValueType!Hash num = 1; // num is declared as int
8141 * Get the Value type of an Associative Array.
8143 alias ValueType(V : V[K], K) = V;
8146 @safe unittest
8148 alias Hash = int[string];
8149 static assert(is(KeyType!Hash == string));
8150 static assert(is(ValueType!Hash == int));
8151 KeyType!Hash str = "a"; // str is declared as string
8152 ValueType!Hash num = 1; // num is declared as int
8156 Params:
8157 T = A built in integral or vector type.
8159 Returns:
8160 The corresponding unsigned numeric type for `T` with the
8161 same type qualifiers.
8163 If `T` is not a integral or vector, a compile-time error is given.
8165 template Unsigned(T)
8167 template Impl(T)
8169 static if (is(T : __vector(V[N]), V, size_t N))
8170 alias Impl = __vector(Impl!V[N]);
8171 else static if (isUnsigned!T)
8172 alias Impl = T;
8173 else static if (isSigned!T && !isFloatingPoint!T)
8175 static if (is(T == byte )) alias Impl = ubyte;
8176 static if (is(T == short)) alias Impl = ushort;
8177 static if (is(T == int )) alias Impl = uint;
8178 static if (is(T == long )) alias Impl = ulong;
8179 static if (is(ucent) && is(T == cent )) alias Impl = ucent;
8181 else
8182 static assert(false, "Type " ~ T.stringof ~
8183 " does not have an Unsigned counterpart");
8186 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8190 @safe unittest
8192 static assert(is(Unsigned!(int) == uint));
8193 static assert(is(Unsigned!(long) == ulong));
8194 static assert(is(Unsigned!(const short) == const ushort));
8195 static assert(is(Unsigned!(immutable byte) == immutable ubyte));
8196 static assert(is(Unsigned!(inout int) == inout uint));
8200 /// Unsigned types are forwarded
8201 @safe unittest
8203 static assert(is(Unsigned!(uint) == uint));
8204 static assert(is(Unsigned!(const uint) == const uint));
8206 static assert(is(Unsigned!(ubyte) == ubyte));
8207 static assert(is(Unsigned!(immutable uint) == immutable uint));
8210 @safe unittest
8212 alias U1 = Unsigned!int;
8213 alias U2 = Unsigned!(const(int));
8214 alias U3 = Unsigned!(immutable(int));
8215 static assert(is(U1 == uint));
8216 static assert(is(U2 == const(uint)));
8217 static assert(is(U3 == immutable(uint)));
8218 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8220 alias UV1 = Unsigned!(__vector(int[4]));
8221 alias UV2 = Unsigned!(const(__vector(int[4])));
8222 static assert(is(UV1 == __vector(uint[4])));
8223 static assert(is(UV2 == const(__vector(uint[4]))));
8225 //struct S {}
8226 //alias U2 = Unsigned!S;
8227 //alias U3 = Unsigned!double;
8228 static if (is(ucent))
8230 alias U4 = Unsigned!cent;
8231 alias U5 = Unsigned!(const(cent));
8232 alias U6 = Unsigned!(immutable(cent));
8233 static assert(is(U4 == ucent));
8234 static assert(is(U5 == const(ucent)));
8235 static assert(is(U6 == immutable(ucent)));
8240 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
8241 than one type is of the same size, the leftmost argument of these in will be
8242 returned.
8244 template Largest(T...)
8245 if (T.length >= 1)
8247 alias Largest = T[0];
8248 static foreach (U; T[1 .. $])
8249 Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8253 @safe unittest
8255 static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8256 static assert(is(Largest!(ulong, double) == ulong));
8257 static assert(is(Largest!(double, ulong) == double));
8258 static assert(is(Largest!(uint, byte, double, short) == double));
8259 static if (is(ucent))
8260 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8264 Returns the corresponding signed type for T. T must be a numeric integral type,
8265 otherwise a compile-time error occurs.
8267 template Signed(T)
8269 template Impl(T)
8271 static if (is(T : __vector(V[N]), V, size_t N))
8272 alias Impl = __vector(Impl!V[N]);
8273 else static if (isSigned!T)
8274 alias Impl = T;
8275 else static if (isUnsigned!T)
8277 static if (is(T == ubyte )) alias Impl = byte;
8278 static if (is(T == ushort)) alias Impl = short;
8279 static if (is(T == uint )) alias Impl = int;
8280 static if (is(T == ulong )) alias Impl = long;
8281 static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8283 else
8284 static assert(false, "Type " ~ T.stringof ~
8285 " does not have an Signed counterpart");
8288 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8292 @safe unittest
8294 alias S1 = Signed!uint;
8295 static assert(is(S1 == int));
8296 alias S2 = Signed!(const(uint));
8297 static assert(is(S2 == const(int)));
8298 alias S3 = Signed!(immutable(uint));
8299 static assert(is(S3 == immutable(int)));
8300 static if (is(ucent))
8302 alias S4 = Signed!ucent;
8303 static assert(is(S4 == cent));
8307 @safe unittest
8309 static assert(is(Signed!float == float));
8310 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8312 alias SV1 = Signed!(__vector(uint[4]));
8313 alias SV2 = Signed!(const(__vector(uint[4])));
8314 static assert(is(SV1 == __vector(int[4])));
8315 static assert(is(SV2 == const(__vector(int[4]))));
8321 Returns the most negative value of the numeric type T.
8323 template mostNegative(T)
8324 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8326 static if (is(typeof(T.min_normal)))
8327 enum mostNegative = -T.max;
8328 else static if (T.min == 0)
8329 enum byte mostNegative = 0;
8330 else
8331 enum mostNegative = T.min;
8335 @safe unittest
8337 static assert(mostNegative!float == -float.max);
8338 static assert(mostNegative!double == -double.max);
8339 static assert(mostNegative!real == -real.max);
8340 static assert(mostNegative!bool == false);
8344 @safe unittest
8346 import std.meta : AliasSeq;
8348 static foreach (T; AliasSeq!(bool, byte, short, int, long))
8349 static assert(mostNegative!T == T.min);
8351 static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8352 static assert(mostNegative!T == 0);
8356 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8357 to in multi-term arithmetic expressions.
8359 template Promoted(T)
8360 if (isScalarType!T)
8362 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8366 @safe unittest
8368 ubyte a = 3, b = 5;
8369 static assert(is(typeof(a * b) == Promoted!ubyte));
8370 static assert(is(Promoted!ubyte == int));
8372 static assert(is(Promoted!(shared(bool)) == shared(int)));
8373 static assert(is(Promoted!(const(int)) == const(int)));
8374 static assert(is(Promoted!double == double));
8377 @safe unittest
8379 // promote to int:
8380 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8382 static assert(is(Promoted!T == int));
8383 static assert(is(Promoted!(shared(const T)) == shared(const int)));
8386 // already promoted:
8387 static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8389 static assert(is(Promoted!T == T));
8390 static assert(is(Promoted!(immutable(T)) == immutable(T)));
8394 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8395 // Misc.
8396 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8399 Returns the mangled name of symbol or type `sth`.
8401 `mangledName` is the same as builtin `.mangleof` property, but
8402 might be more convenient in generic code, e.g. as a template argument
8403 when invoking staticMap.
8405 enum mangledName(alias sth) = sth.mangleof;
8408 @safe unittest
8410 import std.meta : AliasSeq;
8411 alias TL = staticMap!(mangledName, int, const int, immutable int);
8412 static assert(TL == AliasSeq!("i", "xi", "yi"));
8415 version (StdUnittest) private void freeFunc(string);
8417 @safe unittest
8419 class C { int value() @property { return 0; } }
8420 static assert(mangledName!int == int.mangleof);
8421 static assert(mangledName!C == C.mangleof);
8422 static assert(mangledName!(C.value) == C.value.mangleof);
8423 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8424 static assert(mangledName!mangledName == "3std6traits11mangledName");
8425 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8426 int x;
8427 // https://issues.dlang.org/show_bug.cgi?id=9148
8428 static if (is(typeof({ return x; }) : int delegate() pure))
8429 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
8430 else
8431 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
8434 @system unittest
8436 // @system due to demangle
8437 // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8438 import std.demangle : demangle;
8439 int foo;
8440 auto foo_demangled = demangle(mangledName!foo);
8441 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8442 foo_demangled);
8444 void bar();
8445 auto bar_demangled = demangle(mangledName!bar);
8446 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8451 // XXX Select & select should go to another module. (functional or algorithm?)
8454 Aliases itself to `T[0]` if the boolean `condition` is `true`
8455 and to `T[1]` otherwise.
8457 template Select(bool condition, T...)
8458 if (T.length == 2)
8460 import std.meta : Alias;
8461 alias Select = Alias!(T[!condition]);
8465 @safe unittest
8467 // can select types
8468 static assert(is(Select!(true, int, long) == int));
8469 static assert(is(Select!(false, int, long) == long));
8470 static struct Foo {}
8471 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8473 // can select symbols
8474 int a = 1;
8475 int b = 2;
8476 alias selA = Select!(true, a, b);
8477 alias selB = Select!(false, a, b);
8478 assert(selA == 1);
8479 assert(selB == 2);
8481 // can select (compile-time) expressions
8482 enum val = Select!(false, -4, 9 - 6);
8483 static assert(val == 3);
8487 Select one of two functions to run via template parameter.
8489 Params:
8490 cond = A `bool` which determines which function is run
8491 a = The first function
8492 b = The second function
8494 Returns:
8495 `a` without evaluating `b` if `cond` is `true`.
8496 Otherwise, returns `b` without evaluating `a`.
8498 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8499 /// Ditto
8500 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8503 @safe unittest
8505 real run() { return 0; }
8506 int fail() { assert(0); }
8507 auto a = select!true(run(), fail());
8508 auto b = select!false(fail(), run());
8509 static assert(is(typeof(a) == real));
8510 static assert(is(typeof(b) == real));
8514 Determine if a symbol has a given
8515 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8517 See_Also:
8518 $(LREF getUDAs)
8520 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8523 @safe unittest
8525 enum E;
8526 struct S {}
8528 @("alpha") int a;
8529 static assert(hasUDA!(a, "alpha"));
8530 static assert(!hasUDA!(a, S));
8531 static assert(!hasUDA!(a, E));
8533 @(E) int b;
8534 static assert(!hasUDA!(b, "alpha"));
8535 static assert(!hasUDA!(b, S));
8536 static assert(hasUDA!(b, E));
8538 @E int c;
8539 static assert(!hasUDA!(c, "alpha"));
8540 static assert(!hasUDA!(c, S));
8541 static assert(hasUDA!(c, E));
8543 @(S, E) int d;
8544 static assert(!hasUDA!(d, "alpha"));
8545 static assert(hasUDA!(d, S));
8546 static assert(hasUDA!(d, E));
8548 @S int e;
8549 static assert(!hasUDA!(e, "alpha"));
8550 static assert(hasUDA!(e, S));
8551 static assert(!hasUDA!(e, S()));
8552 static assert(!hasUDA!(e, E));
8554 @S() int f;
8555 static assert(!hasUDA!(f, "alpha"));
8556 static assert(hasUDA!(f, S));
8557 static assert(hasUDA!(f, S()));
8558 static assert(!hasUDA!(f, E));
8560 @(S, E, "alpha") int g;
8561 static assert(hasUDA!(g, "alpha"));
8562 static assert(hasUDA!(g, S));
8563 static assert(hasUDA!(g, E));
8565 @(100) int h;
8566 static assert(hasUDA!(h, 100));
8568 struct Named { string name; }
8570 @Named("abc") int i;
8571 static assert(hasUDA!(i, Named));
8572 static assert(hasUDA!(i, Named("abc")));
8573 static assert(!hasUDA!(i, Named("def")));
8575 struct AttrT(T)
8577 string name;
8578 T value;
8581 @AttrT!int("answer", 42) int j;
8582 static assert(hasUDA!(j, AttrT));
8583 static assert(hasUDA!(j, AttrT!int));
8584 static assert(!hasUDA!(j, AttrT!string));
8586 @AttrT!string("hello", "world") int k;
8587 static assert(hasUDA!(k, AttrT));
8588 static assert(!hasUDA!(k, AttrT!int));
8589 static assert(hasUDA!(k, AttrT!string));
8591 struct FuncAttr(alias f) { alias func = f; }
8592 static int fourtyTwo() { return 42; }
8593 static size_t getLen(string s) { return s.length; }
8595 @FuncAttr!getLen int l;
8596 static assert(hasUDA!(l, FuncAttr));
8597 static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8598 static assert(hasUDA!(l, FuncAttr!getLen));
8599 static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8600 static assert(!hasUDA!(l, FuncAttr!getLen()));
8602 @FuncAttr!getLen() int m;
8603 static assert(hasUDA!(m, FuncAttr));
8604 static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8605 static assert(hasUDA!(m, FuncAttr!getLen));
8606 static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8607 static assert(hasUDA!(m, FuncAttr!getLen()));
8611 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8612 from the given symbol.
8614 If the UDA is a type, then any UDAs of the same type on the symbol will
8615 match. If the UDA is a template for a type, then any UDA which is an
8616 instantiation of that template will match. And if the UDA is a value,
8617 then any UDAs on the symbol which are equal to that value will match.
8619 See_Also:
8620 $(LREF hasUDA)
8622 template getUDAs(alias symbol, alias attribute)
8624 import std.meta : Filter;
8626 alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8630 @safe unittest
8632 struct Attr
8634 string name;
8635 int value;
8638 @Attr("Answer", 42) int a;
8639 static assert(getUDAs!(a, Attr).length == 1);
8640 static assert(getUDAs!(a, Attr)[0].name == "Answer");
8641 static assert(getUDAs!(a, Attr)[0].value == 42);
8643 @(Attr("Answer", 42), "string", 9999) int b;
8644 static assert(getUDAs!(b, Attr).length == 1);
8645 static assert(getUDAs!(b, Attr)[0].name == "Answer");
8646 static assert(getUDAs!(b, Attr)[0].value == 42);
8648 @Attr("Answer", 42) @Attr("Pi", 3) int c;
8649 static assert(getUDAs!(c, Attr).length == 2);
8650 static assert(getUDAs!(c, Attr)[0].name == "Answer");
8651 static assert(getUDAs!(c, Attr)[0].value == 42);
8652 static assert(getUDAs!(c, Attr)[1].name == "Pi");
8653 static assert(getUDAs!(c, Attr)[1].value == 3);
8655 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8656 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8657 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8659 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8661 struct AttrT(T)
8663 string name;
8664 T value;
8667 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8668 static assert(getUDAs!(d, AttrT).length == 2);
8669 static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8670 static assert(getUDAs!(d, AttrT)[0].value == 42);
8671 static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8672 static assert(getUDAs!(d, AttrT)[1].value == 3);
8674 static assert(getUDAs!(d, AttrT!uint).length == 1);
8675 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8676 static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8678 static assert(getUDAs!(d, AttrT!int).length == 1);
8679 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8680 static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8682 struct SimpleAttr {}
8684 @SimpleAttr int e;
8685 static assert(getUDAs!(e, SimpleAttr).length == 1);
8686 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8688 @SimpleAttr() int f;
8689 static assert(getUDAs!(f, SimpleAttr).length == 1);
8690 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8692 struct FuncAttr(alias f) { alias func = f; }
8693 static int add42(int v) { return v + 42; }
8694 static string concat(string l, string r) { return l ~ r; }
8696 @FuncAttr!add42 int g;
8697 static assert(getUDAs!(g, FuncAttr).length == 1);
8698 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8700 static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8701 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8703 static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8705 static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8706 static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8708 @FuncAttr!add42() int h;
8709 static assert(getUDAs!(h, FuncAttr).length == 1);
8710 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8712 static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8713 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8715 static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8716 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8718 static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8719 static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8721 @("alpha") @(42) int i;
8722 static assert(getUDAs!(i, "alpha").length == 1);
8723 static assert(getUDAs!(i, "alpha")[0] == "alpha");
8725 static assert(getUDAs!(i, 42).length == 1);
8726 static assert(getUDAs!(i, 42)[0] == 42);
8728 static assert(getUDAs!(i, 'c').length == 0);
8731 private template isDesiredUDA(alias attribute)
8733 template isDesiredUDA(alias toCheck)
8735 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8737 static if (__traits(compiles, toCheck == attribute))
8738 enum isDesiredUDA = toCheck == attribute;
8739 else
8740 enum isDesiredUDA = false;
8742 else static if (is(typeof(toCheck)))
8744 static if (__traits(isTemplate, attribute))
8745 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck));
8746 else
8747 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8749 else static if (__traits(isTemplate, attribute))
8750 enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8751 else
8752 enum isDesiredUDA = is(toCheck == attribute);
8757 Params:
8758 symbol = The aggregate type or module to search
8759 attribute = The user-defined attribute to search for
8761 Returns:
8762 All symbols within `symbol` that have the given UDA `attribute`.
8764 Note:
8765 This is not recursive; it will not search for symbols within symbols such as
8766 nested structs or unions.
8768 template getSymbolsByUDA(alias symbol, alias attribute)
8770 alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8772 // if the symbol itself has the UDA, tack it on to the front of the list
8773 static if (hasUDA!(symbol, attribute))
8774 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8775 else
8776 alias getSymbolsByUDA = membersWithUDA;
8780 @safe unittest
8782 enum Attr;
8783 struct A
8785 @Attr int a;
8786 int b;
8789 static assert(getSymbolsByUDA!(A, Attr).length == 1);
8790 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8794 @safe unittest
8796 enum Attr;
8798 static struct A
8800 @Attr int a;
8801 int b;
8802 @Attr void doStuff() {}
8803 void doOtherStuff() {}
8804 static struct Inner
8806 // Not found by getSymbolsByUDA
8807 @Attr int c;
8811 // Finds both variables and functions with the attribute, but
8812 // doesn't include the variables and functions without it.
8813 static assert(getSymbolsByUDA!(A, Attr).length == 2);
8814 // Can access attributes on the symbols returned by getSymbolsByUDA.
8815 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8816 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8819 /// Finds multiple attributes
8820 @safe unittest
8822 static struct UDA { string name; }
8824 static struct B
8826 @UDA("X")
8827 int x;
8828 @UDA("Y")
8829 int y;
8830 @(100)
8831 int z;
8834 // Finds both UDA attributes.
8835 static assert(getSymbolsByUDA!(B, UDA).length == 2);
8836 // Finds one `100` attribute.
8837 static assert(getSymbolsByUDA!(B, 100).length == 1);
8838 // Can get the value of the UDA from the return value
8839 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8842 /// Checks for UDAs on the aggregate symbol itself
8843 @safe unittest
8845 static struct UDA { string name; }
8847 @UDA("A")
8848 static struct C
8850 @UDA("B")
8851 int d;
8854 static assert(getSymbolsByUDA!(C, UDA).length == 2);
8855 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8856 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8859 /// Finds nothing if there is no member with specific UDA
8860 @safe unittest
8862 static struct UDA { string name; }
8864 static struct D
8866 int x;
8869 static assert(getSymbolsByUDA!(D, UDA).length == 0);
8872 // https://issues.dlang.org/show_bug.cgi?id=18314
8873 @safe unittest
8875 enum attr1;
8876 enum attr2;
8878 struct A
8880 @attr1
8881 int n;
8882 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8883 //@attr1
8884 //void foo()(string){}
8885 @attr1
8886 void foo();
8887 @attr2
8888 void foo(int a);
8891 static assert(getSymbolsByUDA!(A, attr1).length == 2);
8892 static assert(getSymbolsByUDA!(A, attr2).length == 1);
8895 // getSymbolsByUDA fails if type has private members
8896 // https://issues.dlang.org/show_bug.cgi?id=15335
8897 @safe unittest
8899 // HasPrivateMembers has, well, private members, one of which has a UDA.
8900 import std.internal.test.uda : Attr, HasPrivateMembers;
8901 // Trying access to private member from another file therefore we do not have access
8902 // for this otherwise we get deprecation warning - not visible from module
8903 // This line is commented because `__traits(getMember)` should also consider
8904 // private members; this is not currently the case, but the PR that
8905 // fixes `__traits(getMember)` is blocked by this specific test.
8906 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8907 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8910 // getSymbolsByUDA works with structs but fails with classes
8911 // https://issues.dlang.org/show_bug.cgi?id=16387
8912 @safe unittest
8914 enum Attr;
8915 class A
8917 @Attr uint a;
8920 alias res = getSymbolsByUDA!(A, Attr);
8921 static assert(res.length == 1);
8922 static assert(res[0].stringof == "a");
8925 // getSymbolsByUDA fails on AliasSeq members
8926 // https://issues.dlang.org/show_bug.cgi?id=18884
8927 @safe unittest
8929 struct X
8931 alias A = AliasSeq!(ulong, uint);
8934 static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8937 // https://issues.dlang.org/show_bug.cgi?id=23776
8938 @safe pure nothrow @nogc unittest
8940 struct T
8942 struct Tag {}
8943 @Tag struct MyStructA {}
8944 @Tag struct MyStructB {}
8945 @Tag struct MyStructC {}
8947 alias tcomponents = getSymbolsByUDA!(T, T.Tag);
8948 static assert(tcomponents.length > 0);
8950 struct X
8952 struct Tag {}
8953 @Tag enum MyEnumA;
8954 @Tag enum MyEnumB;
8955 @Tag enum MyEnumC;
8957 alias xcomponents = getSymbolsByUDA!(X, X.Tag);
8958 static assert(xcomponents.length > 0);
8961 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8962 // https://issues.dlang.org/show_bug.cgi?id=18624
8963 @safe unittest
8965 enum Attr;
8966 struct A
8968 @Attr void a();
8969 @Attr void a(int n);
8970 void b();
8971 @Attr void c();
8974 alias ola = __traits(getOverloads, A, "a");
8975 static assert(__traits(isSame, getSymbolsByUDA!(A, Attr),
8976 AliasSeq!(ola[0], ola[1], A.c)));
8979 // getSymbolsByUDA no longer works on modules
8980 // https://issues.dlang.org/show_bug.cgi?id=20054
8981 version (StdUnittest)
8983 @("Issue20054")
8984 void issue20054() {}
8985 static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8988 private template isAliasSeq(Args...)
8990 static if (Args.length != 1)
8991 enum isAliasSeq = true;
8992 else
8993 enum isAliasSeq = false;
8996 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8998 import std.meta : Alias, AliasSeq, Filter;
8999 static if (names.length == 0)
9001 alias getSymbolsByUDAImpl = AliasSeq!();
9003 else
9005 alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
9007 // Filtering inaccessible members.
9008 static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
9010 alias getSymbolsByUDAImpl = tail;
9012 else
9014 alias member = __traits(getMember, symbol, names[0]);
9016 // Filtering not compiled members such as alias of basic types.
9017 static if (isAliasSeq!member ||
9018 (isType!member && !isAggregateType!member && !is(member == enum)))
9020 alias getSymbolsByUDAImpl = tail;
9022 // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
9023 else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
9025 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
9026 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
9027 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
9029 else static if (hasUDA!(member, attribute))
9031 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
9033 else
9035 alias getSymbolsByUDAImpl = tail;
9042 Returns: `true` iff all types `Ts` are the same.
9044 enum bool allSameType(Ts...) =
9046 static foreach (T; Ts[Ts.length > 1 .. $])
9047 static if (!is(Ts[0] == T))
9048 if (__ctfe) // Dodge the "statement is unreachable" warning
9049 return false;
9050 return true;
9051 }();
9054 @safe unittest
9056 static assert(allSameType!());
9057 static assert(allSameType!(int));
9058 static assert(allSameType!(int, int));
9059 static assert(allSameType!(int, int, int));
9060 static assert(allSameType!(float, float, float));
9061 static assert(!allSameType!(int, double));
9062 static assert(!allSameType!(int, float, double));
9063 static assert(!allSameType!(int, float, double, real));
9064 static assert(!allSameType!(short, int, float, double, real));
9068 Returns: `true` iff the type `T` can be tested in an $(D
9069 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
9071 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
9074 @safe unittest
9076 class C;
9077 struct S1;
9078 struct S2
9080 T opCast(T)() const;
9083 static assert( ifTestable!bool);
9084 static assert( ifTestable!int);
9085 static assert( ifTestable!(S1*));
9086 static assert( ifTestable!(typeof(null)));
9087 static assert( ifTestable!(int[]));
9088 static assert( ifTestable!(int[string]));
9089 static assert( ifTestable!S2);
9090 static assert( ifTestable!C);
9091 static assert(!ifTestable!S1);
9094 @safe unittest
9096 import std.meta : AliasSeq, allSatisfy;
9097 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
9098 struct BoolWrapper { bool value; }
9099 static assert(!ifTestable!(bool, a => BoolWrapper(a)));
9103 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
9104 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
9106 * Returns:
9107 * `true` if `X` is a type, `false` otherwise
9109 enum isType(alias X) = is(X);
9112 @safe unittest
9114 struct S {
9115 template Test() {}
9117 class C {}
9118 interface I {}
9119 union U {}
9120 static assert(isType!int);
9121 static assert(isType!string);
9122 static assert(isType!(int[int]));
9123 static assert(isType!S);
9124 static assert(isType!C);
9125 static assert(isType!I);
9126 static assert(isType!U);
9128 int n;
9129 void func(){}
9130 static assert(!isType!n);
9131 static assert(!isType!func);
9132 static assert(!isType!(S.Test));
9133 static assert(!isType!(S.Test!()));
9137 * Detect whether symbol or type `X` is a function. This is different that finding
9138 * if a symbol is callable or satisfying `is(X == function)`, it finds
9139 * specifically if the symbol represents a normal function declaration, i.e.
9140 * not a delegate or a function pointer.
9142 * Returns:
9143 * `true` if `X` is a function, `false` otherwise
9145 * See_Also:
9146 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
9147 * respectively.
9149 template isFunction(alias X)
9151 static if (is(typeof(&X) U : U*) && is(U == function) ||
9152 is(typeof(&X) U == delegate))
9154 // x is a (nested) function symbol.
9155 enum isFunction = true;
9157 else static if (is(X T))
9159 // x is a type. Take the type of it and examine.
9160 enum isFunction = is(T == function);
9162 else
9163 enum isFunction = false;
9167 @safe unittest
9169 static void func(){}
9170 static assert(isFunction!func);
9172 struct S
9174 void func(){}
9176 static assert(isFunction!(S.func));
9180 * Detect whether `X` is a final method or class.
9182 * Returns:
9183 * `true` if `X` is final, `false` otherwise
9185 template isFinal(alias X)
9187 static if (is(X == class))
9188 enum isFinal = __traits(isFinalClass, X);
9189 else static if (isFunction!X)
9190 enum isFinal = __traits(isFinalFunction, X);
9191 else
9192 enum isFinal = false;
9196 @safe unittest
9198 class C
9200 void nf() {}
9201 static void sf() {}
9202 final void ff() {}
9204 final class FC { }
9206 static assert(!isFinal!(C));
9207 static assert( isFinal!(FC));
9209 static assert(!isFinal!(C.nf));
9210 static assert(!isFinal!(C.sf));
9211 static assert( isFinal!(C.ff));
9215 + Determines whether the type `S` can be copied.
9216 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9217 + Copying for structs can be disabled by using `@disable this(this)`.
9219 + See also: $(DDSUBLINK spec/traits, isCopyable, `__traits(isCopyable, S)`)
9220 + Params:
9221 + S = The type to check.
9223 + Returns:
9224 + `true` if `S` can be copied. `false` otherwise.
9226 enum isCopyable(S) = __traits(isCopyable, S);
9229 @safe unittest
9231 struct S1 {} // Fine. Can be copied
9232 struct S2 { this(this) {}} // Fine. Can be copied
9233 struct S3 {@disable this(this); } // Not fine. Copying is disabled.
9234 struct S4 {S3 s;} // Not fine. A field has copying disabled.
9236 class C1 {}
9238 static assert( isCopyable!S1);
9239 static assert( isCopyable!S2);
9240 static assert(!isCopyable!S3);
9241 static assert(!isCopyable!S4);
9243 static assert(isCopyable!C1);
9244 static assert(isCopyable!int);
9245 static assert(isCopyable!(int[]));
9249 * The parameter type deduced by IFTI when an expression of type T is passed as
9250 * an argument to a template function.
9252 * For all types other than pointer and slice types, `DeducedParameterType!T`
9253 * is the same as `T`. For pointer and slice types, it is `T` with the
9254 * outer-most layer of qualifiers dropped.
9256 package(std) alias DeducedParameterType(T) = DeducedParameterTypeImpl!T;
9257 /// ditto
9258 package(std) alias DeducedParameterType(alias T) = DeducedParameterTypeImpl!T;
9260 private template DeducedParameterTypeImpl(T)
9262 static if (is(T == U*, U) || is(T == U[], U))
9263 alias DeducedParameterTypeImpl = Unqual!T;
9264 else
9265 alias DeducedParameterTypeImpl = T;
9268 @safe unittest
9270 static assert(is(DeducedParameterType!(const(int)) == const(int)));
9271 static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
9273 static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
9274 static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
9277 @safe unittest
9279 static struct NoCopy
9281 @disable this(this);
9284 static assert(is(DeducedParameterType!NoCopy == NoCopy));
9285 static assert(is(DeducedParameterType!(inout(NoCopy)) == inout(NoCopy)));
9288 @safe unittest
9290 static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
9293 private auto dip1000Test(int x) {return *&x;}
9294 // We don't use isSafe, because betterC client code needs to instantiate
9295 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9296 // __cmp of two strings, so using it would instantate that here instead. That
9297 // won't do because betterC compilations do not link the Phobos binary in.
9298 package(std) enum dip1000Enabled
9299 = is(typeof(&dip1000Test) : int function(int) @safe);