libbacktrace: don't fail if symbol size is unknown
[official-gcc.git] / libphobos / src / std / traits.d
blob2e7a4f6a30bfbb614a0c66248da7de59cbac9d4f
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`.
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 { return 0; }
2234 static assert(is( typeof(C.value) == int ));
2235 static assert(is( FunctionTypeOf!(C.value) == function ));
2238 @system unittest
2240 int test(int a);
2241 int propGet() @property;
2242 int propSet(int a) @property;
2243 int function(int) test_fp;
2244 int delegate(int) test_dg;
2245 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) ));
2246 static assert(is( typeof(test) == FunctionTypeOf!test ));
2247 static assert(is( typeof(test) == FunctionTypeOf!test_fp ));
2248 static assert(is( typeof(test) == FunctionTypeOf!test_dg ));
2249 alias int GetterType() @property;
2250 alias int SetterType(int) @property;
2251 static assert(is( FunctionTypeOf!propGet == GetterType ));
2252 static assert(is( FunctionTypeOf!propSet == SetterType ));
2254 interface Prop { int prop() @property; }
2255 Prop prop;
2256 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType ));
2257 static assert(is( FunctionTypeOf!(prop.prop) == GetterType ));
2259 class Callable { int opCall(int) { return 0; } }
2260 auto call = new Callable;
2261 static assert(is( FunctionTypeOf!call == typeof(test) ));
2263 struct StaticCallable { static int opCall(int) { return 0; } }
2264 StaticCallable stcall_val;
2265 StaticCallable* stcall_ptr;
2266 static assert(is( FunctionTypeOf!stcall_val == typeof(test) ));
2267 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) ));
2269 struct TemplatedOpCallF { int opCall()(int) { return 0; } }
2270 static assert(is( FunctionTypeOf!TemplatedOpCallF == typeof(TemplatedOpCallF.opCall!()) ));
2272 int foovar;
2273 struct TemplatedOpCallDg { int opCall()() { return foovar; } }
2274 static assert(is( FunctionTypeOf!TemplatedOpCallDg == typeof(TemplatedOpCallDg.opCall!()) ));
2276 interface Overloads
2278 void test(string);
2279 real test(real);
2280 int test(int);
2281 int test() @property;
2283 alias ov = __traits(getVirtualMethods, Overloads, "test");
2284 alias F_ov0 = FunctionTypeOf!(ov[0]);
2285 alias F_ov1 = FunctionTypeOf!(ov[1]);
2286 alias F_ov2 = FunctionTypeOf!(ov[2]);
2287 alias F_ov3 = FunctionTypeOf!(ov[3]);
2288 static assert(is(F_ov0* == void function(string)));
2289 static assert(is(F_ov1* == real function(real)));
2290 static assert(is(F_ov2* == int function(int)));
2291 static assert(is(F_ov3* == int function() @property));
2293 alias F_dglit = FunctionTypeOf!((int a){ return a; });
2294 static assert(is(F_dglit* : int function(int)));
2298 * Constructs a new function or delegate type with the same basic signature
2299 * as the given one, but different attributes (including linkage).
2301 * This is especially useful for adding/removing attributes to/from types in
2302 * generic code, where the actual type name cannot be spelt out.
2304 * Params:
2305 * T = The base type.
2306 * linkage = The desired linkage of the result type.
2307 * attrs = The desired $(LREF FunctionAttribute)s of the result type.
2309 template SetFunctionAttributes(T, string linkage, uint attrs)
2310 if (isFunctionPointer!T || isDelegate!T)
2312 mixin({
2313 import std.algorithm.searching : canFind;
2315 static assert(!(attrs & FunctionAttribute.trusted) ||
2316 !(attrs & FunctionAttribute.safe),
2317 "Cannot have a function/delegate that is both trusted and safe.");
2319 static immutable linkages = ["D", "C", "Windows", "C++", "System"];
2320 static assert(canFind(linkages, linkage), "Invalid linkage '" ~
2321 linkage ~ "', must be one of " ~ linkages.stringof ~ ".");
2323 string result = "alias ";
2325 static if (linkage != "D")
2326 result ~= "extern(" ~ linkage ~ ") ";
2328 static if (attrs & FunctionAttribute.ref_)
2329 result ~= "ref ";
2331 result ~= "ReturnType!T";
2333 static if (isDelegate!T)
2334 result ~= " delegate";
2335 else
2336 result ~= " function";
2338 result ~= "(";
2340 static if (Parameters!T.length > 0)
2341 result ~= "Parameters!T";
2343 enum varStyle = variadicFunctionStyle!T;
2344 static if (varStyle == Variadic.c)
2345 result ~= ", ...";
2346 else static if (varStyle == Variadic.d)
2347 result ~= "...";
2348 else static if (varStyle == Variadic.typesafe)
2349 result ~= "...";
2351 result ~= ")";
2353 static if (attrs & FunctionAttribute.pure_)
2354 result ~= " pure";
2355 static if (attrs & FunctionAttribute.nothrow_)
2356 result ~= " nothrow";
2357 static if (attrs & FunctionAttribute.property)
2358 result ~= " @property";
2359 static if (attrs & FunctionAttribute.trusted)
2360 result ~= " @trusted";
2361 static if (attrs & FunctionAttribute.safe)
2362 result ~= " @safe";
2363 static if (attrs & FunctionAttribute.nogc)
2364 result ~= " @nogc";
2365 static if (attrs & FunctionAttribute.system)
2366 result ~= " @system";
2367 static if (attrs & FunctionAttribute.const_)
2368 result ~= " const";
2369 static if (attrs & FunctionAttribute.immutable_)
2370 result ~= " immutable";
2371 static if (attrs & FunctionAttribute.inout_)
2372 result ~= " inout";
2373 static if (attrs & FunctionAttribute.shared_)
2374 result ~= " shared";
2375 static if (attrs & FunctionAttribute.return_)
2376 result ~= " return";
2377 static if (attrs & FunctionAttribute.live)
2378 result ~= " @live";
2380 result ~= " SetFunctionAttributes;";
2381 return result;
2382 }());
2385 /// Ditto
2386 template SetFunctionAttributes(T, string linkage, uint attrs)
2387 if (is(T == function))
2389 // To avoid a lot of syntactic headaches, we just use the above version to
2390 // operate on the corresponding function pointer type and then remove the
2391 // indirection again.
2392 alias SetFunctionAttributes = FunctionTypeOf!(SetFunctionAttributes!(T*, linkage, attrs));
2396 @safe unittest
2398 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
2400 auto assumePure(T)(T t)
2401 if (isFunctionPointer!T || isDelegate!T)
2403 enum attrs = functionAttributes!T | FunctionAttribute.pure_;
2404 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
2407 int f()
2409 import core.thread : getpid;
2410 return getpid();
2413 int g() pure @trusted
2415 auto pureF = assumePure(&f);
2416 return pureF();
2418 assert(g() > 0);
2421 version (StdUnittest)
2423 private:
2424 // Some function types to test.
2425 int sc(scope int, ref int, out int, lazy int, int);
2426 extern(System) int novar();
2427 extern(C) int cstyle(int, ...);
2428 extern(D) int dstyle(...);
2429 extern(D) int typesafe(int[]...);
2431 @safe unittest
2433 import std.algorithm.iteration : reduce;
2435 alias FA = FunctionAttribute;
2436 static foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle),
2437 typeof(&dstyle), typeof(&typesafe)))
2439 static foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT))
2441 enum linkage = functionLinkage!T;
2442 enum attrs = functionAttributes!T;
2444 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T),
2445 "Identity check failed for: " ~ T.stringof);
2447 // Check that all linkage types work (D-style variadics require D linkage).
2448 static if (variadicFunctionStyle!T != Variadic.d)
2450 static foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++"))
2452 alias New = SetFunctionAttributes!(T, newLinkage, attrs);
2453 static assert(functionLinkage!New == newLinkage,
2454 "Linkage test failed for: " ~ T.stringof ~ ", " ~ newLinkage ~
2455 " (got " ~ New.stringof ~ ")");
2459 // Add @safe.
2460 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe);
2461 static assert(functionAttributes!T1 == FA.safe);
2463 // Add all known attributes, excluding conflicting ones.
2464 enum allAttrs = reduce!"a | b"([EnumMembers!FA])
2465 & ~FA.safe & ~FA.property & ~FA.const_ & ~FA.immutable_ & ~FA.inout_
2466 & ~FA.shared_ & ~FA.system & ~FA.return_ & ~FA.scope_;
2468 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs);
2469 static assert(functionAttributes!T2 == allAttrs);
2471 // Strip all attributes again.
2472 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none);
2473 static assert(is(T3 == T));
2479 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2480 // Aggregate Types
2481 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2484 Determines whether `T` is a class nested inside another class
2485 and that `T.outer` is the implicit reference to the outer class
2486 (i.e. `outer` has not been used as a field or method name)
2488 Params:
2489 T = type to test
2491 Returns:
2492 `true` if `T` is a class nested inside another, with the conditions described above;
2493 `false` otherwise
2495 template isInnerClass(T)
2496 if (is(T == class))
2498 static if (is(typeof(T.outer)))
2500 bool hasOuterMember(string[] members...)
2502 foreach (m; members)
2504 if (m == "outer")
2505 return true;
2507 return false;
2509 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) &&
2510 !hasOuterMember(__traits(allMembers, T));
2512 else
2513 enum isInnerClass = false;
2517 @safe unittest
2519 class C
2521 int outer;
2523 static assert(!isInnerClass!C);
2525 class Outer1
2527 class Inner1 { }
2528 class Inner2
2530 int outer;
2533 static assert(isInnerClass!(Outer1.Inner1));
2534 static assert(!isInnerClass!(Outer1.Inner2));
2536 static class Outer2
2538 static class Inner
2540 int outer;
2543 static assert(!isInnerClass!(Outer2.Inner));
2547 Determines whether `T` has its own context pointer.
2548 `T` must be either `class`, `struct`, or `union`.
2550 See also: $(DDSUBLINK spec/traits, isNested, `__traits(isNested, T)`)
2552 template isNested(T)
2553 if (is(T == class) || is(T == struct) || is(T == union))
2555 enum isNested = __traits(isNested, T);
2559 @safe unittest
2561 static struct S { }
2562 static assert(!isNested!S);
2564 int i;
2565 struct NestedStruct { void f() { ++i; } }
2566 static assert(isNested!NestedStruct);
2570 Determines whether `T` or any of its representation types
2571 have a context pointer.
2573 template hasNested(T)
2575 import std.meta : Filter;
2577 static if (isStaticArray!T && T.length)
2578 enum hasNested = hasNested!(typeof(T.init[0]));
2579 else static if (is(T == class) || is(T == struct) || is(T == union))
2581 // prevent infinite recursion for class with member of same type
2582 enum notSame(U) = !is(immutable T == immutable U);
2583 enum hasNested = isNested!T ||
2584 anySatisfy!(.hasNested, Filter!(notSame, Fields!T));
2586 else
2587 enum hasNested = false;
2591 @safe unittest
2593 static struct S { }
2595 int i;
2596 struct NS { void f() { ++i; } }
2598 static assert(!hasNested!(S[2]));
2599 static assert(hasNested!(NS[2]));
2602 @safe unittest
2604 static assert(!__traits(compiles, isNested!int));
2605 static assert(!hasNested!int);
2607 static struct StaticStruct { }
2608 static assert(!isNested!StaticStruct);
2609 static assert(!hasNested!StaticStruct);
2611 int i;
2612 struct NestedStruct { void f() { ++i; } }
2613 static assert( isNested!NestedStruct);
2614 static assert( hasNested!NestedStruct);
2615 static assert( isNested!(immutable NestedStruct));
2616 static assert( hasNested!(immutable NestedStruct));
2618 static assert(!__traits(compiles, isNested!(NestedStruct[1])));
2619 static assert( hasNested!(NestedStruct[1]));
2620 static assert(!hasNested!(NestedStruct[0]));
2622 struct S1 { NestedStruct nested; }
2623 static assert(!isNested!S1);
2624 static assert( hasNested!S1);
2626 static struct S2 { NestedStruct nested; }
2627 static assert(!isNested!S2);
2628 static assert( hasNested!S2);
2630 static struct S3 { NestedStruct[0] nested; }
2631 static assert(!isNested!S3);
2632 static assert(!hasNested!S3);
2634 static union U { NestedStruct nested; }
2635 static assert(!isNested!U);
2636 static assert( hasNested!U);
2638 static class StaticClass { }
2639 static assert(!isNested!StaticClass);
2640 static assert(!hasNested!StaticClass);
2642 class NestedClass { void f() { ++i; } }
2643 static assert( isNested!NestedClass);
2644 static assert( hasNested!NestedClass);
2645 static assert( isNested!(immutable NestedClass));
2646 static assert( hasNested!(immutable NestedClass));
2648 static assert(!__traits(compiles, isNested!(NestedClass[1])));
2649 static assert( hasNested!(NestedClass[1]));
2650 static assert(!hasNested!(NestedClass[0]));
2652 static class A
2654 A a;
2656 static assert(!hasNested!A);
2660 /***
2661 * Get as a tuple the types of the fields of a struct, class, or union.
2662 * This consists of the fields that take up memory space,
2663 * excluding the hidden fields like the virtual function
2664 * table pointer or a context pointer for nested types.
2665 * If `T` isn't a struct, class, interface or union returns a tuple
2666 * with one element `T`.
2668 * History:
2669 * - Returned `AliasSeq!(Interface)` for interfaces prior to 2.097
2671 template Fields(T)
2673 import core.internal.traits : _Fields = Fields;
2674 alias Fields = _Fields!T;
2678 @safe unittest
2680 import std.meta : AliasSeq;
2681 struct S { int x; float y; }
2682 static assert(is(Fields!S == AliasSeq!(int, float)));
2686 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2688 alias FieldTypeTuple = Fields;
2690 @safe unittest
2692 static assert(is(FieldTypeTuple!int == AliasSeq!int));
2694 static struct StaticStruct1 { }
2695 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!()));
2697 static struct StaticStruct2 { int a, b; }
2698 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int)));
2700 int i;
2702 struct NestedStruct1 { void f() { ++i; } }
2703 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!()));
2705 struct NestedStruct2 { int a; void f() { ++i; } }
2706 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int));
2708 class NestedClass { int a; void f() { ++i; } }
2709 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int));
2711 static interface I {}
2712 static assert(is(Fields!I == AliasSeq!()));
2715 //Required for FieldNameTuple
2716 private enum NameOf(alias T) = T.stringof;
2719 * Get as an expression tuple the names of the fields of a struct, class, or
2720 * union. This consists of the fields that take up memory space, excluding the
2721 * hidden fields like the virtual function table pointer or a context pointer
2722 * for nested types.
2723 * Inherited fields (for classes) are not included.
2724 * If `T` isn't a struct, class, interface or union, an
2725 * expression tuple with an empty string is returned.
2727 * History:
2728 * - Returned `AliasSeq!""` for interfaces prior to 2.097
2730 template FieldNameTuple(T)
2732 import std.meta : staticMap;
2733 static if (is(T == struct) || is(T == union))
2734 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]);
2735 else static if (is(T == class) || is(T == interface))
2736 alias FieldNameTuple = staticMap!(NameOf, T.tupleof);
2737 else
2738 alias FieldNameTuple = AliasSeq!"";
2742 @safe unittest
2744 import std.meta : AliasSeq;
2745 struct S { int x; float y; }
2746 static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
2747 static assert(FieldNameTuple!int == AliasSeq!"");
2750 @safe unittest
2752 static assert(FieldNameTuple!int == AliasSeq!"");
2754 static struct StaticStruct1 { }
2755 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!()));
2757 static struct StaticStruct2 { int a, b; }
2758 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b"));
2760 static class StaticClass1 { }
2761 static assert(is(FieldNameTuple!StaticClass1 == AliasSeq!()));
2763 static class StaticClass2 : StaticClass1 { int a, b; }
2764 static assert(FieldNameTuple!StaticClass2 == AliasSeq!("a", "b"));
2766 static class StaticClass3 : StaticClass2 { int c; }
2767 static assert(FieldNameTuple!StaticClass3 == AliasSeq!("c"));
2769 int i;
2771 struct NestedStruct1 { void f() { ++i; } }
2772 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!()));
2774 struct NestedStruct2 { int a; void f() { ++i; } }
2775 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a");
2777 class NestedClass { int a; void f() { ++i; } }
2778 static assert(FieldNameTuple!NestedClass == AliasSeq!"a");
2780 interface I {}
2781 static assert(FieldNameTuple!I == AliasSeq!());
2785 /***
2786 Get the primitive types of the fields of a struct or class, in
2787 topological order.
2789 template RepresentationTypeTuple(T)
2791 static if (is(T == struct) || is(T == union) || is(T == class))
2793 alias RepresentationTypeTuple = staticMapMeta!(RepresentationTypeTupleImpl, FieldTypeTuple!T);
2795 else
2797 alias RepresentationTypeTuple = RepresentationTypeTupleImpl!T;
2802 @safe unittest
2804 struct S1 { int a; float b; }
2805 struct S2 { char[] a; union { S1 b; S1 * c; } }
2806 alias R = RepresentationTypeTuple!S2;
2807 assert(R.length == 4
2808 && is(R[0] == char[]) && is(R[1] == int)
2809 && is(R[2] == float) && is(R[3] == S1*));
2812 @safe unittest
2814 alias S1 = RepresentationTypeTuple!int;
2815 static assert(is(S1 == AliasSeq!int));
2817 struct S2 { int a; }
2818 struct S3 { int a; char b; }
2819 struct S4 { S1 a; int b; S3 c; }
2820 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int));
2821 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char)));
2822 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char)));
2824 struct S11 { int a; float b; }
2825 struct S21 { char[] a; union { S11 b; S11 * c; } }
2826 alias R = RepresentationTypeTuple!S21;
2827 assert(R.length == 4
2828 && is(R[0] == char[]) && is(R[1] == int)
2829 && is(R[2] == float) && is(R[3] == S11*));
2831 class C { int a; float b; }
2832 alias R1 = RepresentationTypeTuple!C;
2833 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float));
2835 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
2836 import std.typecons : Rebindable;
2838 struct S5 { int a; Rebindable!(immutable Object) b; }
2839 alias R2 = RepresentationTypeTuple!S5;
2840 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
2842 static assert(is(RepresentationTypeTuple!noreturn == AliasSeq!noreturn));
2845 @safe unittest
2847 struct VeryLargeType
2849 import std.format : format;
2850 import std.range : iota;
2852 static foreach (i; 500.iota)
2854 mixin(format!"int v%s;"(i));
2858 alias BigList = RepresentationTypeTuple!VeryLargeType;
2861 private template RepresentationTypeTupleImpl(T)
2863 import std.typecons : Rebindable;
2865 static if (is(immutable T == immutable Rebindable!R, R))
2867 alias RepresentationTypeTupleImpl
2868 = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R);
2870 else static if (is(T == struct) || is(T == union))
2872 // @@@BUG@@@ this should work
2873 //alias .RepresentationTypes!(T[0].tupleof)
2874 // RepresentationTypes;
2875 alias RepresentationTypeTupleImpl
2876 = staticMapMeta!(.RepresentationTypeTupleImpl, FieldTypeTuple!(T));
2878 else
2880 alias RepresentationTypeTupleImpl
2881 = AliasSeq!T;
2886 Statically evaluates to `true` if and only if `T`'s
2887 representation contains at least one field of pointer or array type.
2888 Members of class types are not considered raw pointers. Pointers to
2889 immutable objects are not considered raw aliasing.
2891 private template hasRawAliasing(T)
2893 enum hasRawAliasing = anySatisfy!(hasRawAliasingImpl, RepresentationTypeTuple!T);
2897 @safe unittest
2899 // simple types
2900 static assert(!hasRawAliasing!int);
2901 static assert( hasRawAliasing!(char*));
2902 // references aren't raw pointers
2903 static assert(!hasRawAliasing!Object);
2904 // built-in arrays do contain raw pointers
2905 static assert( hasRawAliasing!(int[]));
2906 // aggregate of simple types
2907 struct S1 { int a; double b; }
2908 static assert(!hasRawAliasing!S1);
2909 // indirect aggregation
2910 struct S2 { S1 a; double b; }
2911 static assert(!hasRawAliasing!S2);
2914 // https://issues.dlang.org/show_bug.cgi?id=19228
2915 @safe unittest
2917 static struct C
2919 int*[1] a;
2921 static assert(hasRawAliasing!C);
2924 @safe unittest
2926 // struct with a pointer member
2927 struct S3 { int a; double * b; }
2928 static assert( hasRawAliasing!S3);
2929 // struct with an indirect pointer member
2930 struct S4 { S3 a; double b; }
2931 static assert( hasRawAliasing!S4);
2932 struct S5 { int a; Object z; int c; }
2933 static assert( hasRawAliasing!S3);
2934 static assert( hasRawAliasing!S4);
2935 static assert(!hasRawAliasing!S5);
2937 union S6 { int a; int b; }
2938 union S7 { int a; int * b; }
2939 static assert(!hasRawAliasing!S6);
2940 static assert( hasRawAliasing!S7);
2942 static assert(!hasRawAliasing!(void delegate()));
2943 static assert(!hasRawAliasing!(void delegate() const));
2944 static assert(!hasRawAliasing!(void delegate() immutable));
2945 static assert(!hasRawAliasing!(void delegate() shared));
2946 static assert(!hasRawAliasing!(void delegate() shared const));
2947 static assert(!hasRawAliasing!(const(void delegate())));
2948 static assert(!hasRawAliasing!(immutable(void delegate())));
2950 struct S8 { void delegate() a; int b; Object c; }
2951 class S12 { typeof(S8.tupleof) a; }
2952 class S13 { typeof(S8.tupleof) a; int* b; }
2953 static assert(!hasRawAliasing!S8);
2954 static assert(!hasRawAliasing!S12);
2955 static assert( hasRawAliasing!S13);
2957 enum S9 { a }
2958 static assert(!hasRawAliasing!S9);
2960 // indirect members
2961 struct S10 { S7 a; int b; }
2962 struct S11 { S6 a; int b; }
2963 static assert( hasRawAliasing!S10);
2964 static assert(!hasRawAliasing!S11);
2966 static assert( hasRawAliasing!(int[string]));
2967 static assert(!hasRawAliasing!(immutable(int[string])));
2970 private template hasRawAliasingImpl(T)
2972 static if (is(T foo : U*, U) && !isFunctionPointer!T)
2973 enum hasRawAliasingImpl = !is(U == immutable);
2974 else static if (is(T foo : U[N], U, size_t N))
2975 // separate static ifs to avoid forward reference
2976 static if (is(U == class) || is(U == interface))
2977 enum hasRawAliasingImpl = false;
2978 else
2979 enum hasRawAliasingImpl = hasRawAliasingImpl!U;
2980 else static if (is(T foo : U[], U) && !isStaticArray!(T))
2981 enum hasRawAliasingImpl = !is(U == immutable);
2982 else static if (isAssociativeArray!(T))
2983 enum hasRawAliasingImpl = !is(T == immutable);
2984 else
2985 enum hasRawAliasingImpl = false;
2989 Statically evaluates to `true` if and only if `T`'s
2990 representation contains at least one non-shared field of pointer or
2991 array type. Members of class types are not considered raw pointers.
2992 Pointers to immutable objects are not considered raw aliasing.
2994 private template hasRawUnsharedAliasing(T)
2996 enum hasRawUnsharedAliasing = anySatisfy!(hasRawUnsharedAliasingImpl, RepresentationTypeTuple!T);
3000 @safe unittest
3002 // simple types
3003 static assert(!hasRawUnsharedAliasing!int);
3004 static assert( hasRawUnsharedAliasing!(char*));
3005 static assert(!hasRawUnsharedAliasing!(shared char*));
3006 // references aren't raw pointers
3007 static assert(!hasRawUnsharedAliasing!Object);
3008 // built-in arrays do contain raw pointers
3009 static assert( hasRawUnsharedAliasing!(int[]));
3010 static assert(!hasRawUnsharedAliasing!(shared int[]));
3011 // aggregate of simple types
3012 struct S1 { int a; double b; }
3013 static assert(!hasRawUnsharedAliasing!S1);
3014 // indirect aggregation
3015 struct S2 { S1 a; double b; }
3016 static assert(!hasRawUnsharedAliasing!S2);
3017 // struct with a pointer member
3018 struct S3 { int a; double * b; }
3019 static assert( hasRawUnsharedAliasing!S3);
3020 struct S4 { int a; shared double * b; }
3021 static assert(!hasRawUnsharedAliasing!S4);
3024 @safe unittest
3026 // struct with a pointer member
3027 struct S3 { int a; double * b; }
3028 static assert( hasRawUnsharedAliasing!S3);
3029 struct S4 { int a; shared double * b; }
3030 static assert(!hasRawUnsharedAliasing!S4);
3031 // struct with an indirect pointer member
3032 struct S5 { S3 a; double b; }
3033 static assert( hasRawUnsharedAliasing!S5);
3034 struct S6 { S4 a; double b; }
3035 static assert(!hasRawUnsharedAliasing!S6);
3036 struct S7 { int a; Object z; int c; }
3037 static assert( hasRawUnsharedAliasing!S5);
3038 static assert(!hasRawUnsharedAliasing!S6);
3039 static assert(!hasRawUnsharedAliasing!S7);
3041 union S8 { int a; int b; }
3042 union S9 { int a; int* b; }
3043 union S10 { int a; shared int* b; }
3044 static assert(!hasRawUnsharedAliasing!S8);
3045 static assert( hasRawUnsharedAliasing!S9);
3046 static assert(!hasRawUnsharedAliasing!S10);
3048 static assert(!hasRawUnsharedAliasing!(void delegate()));
3049 static assert(!hasRawUnsharedAliasing!(void delegate() const));
3050 static assert(!hasRawUnsharedAliasing!(void delegate() immutable));
3051 static assert(!hasRawUnsharedAliasing!(void delegate() shared));
3052 static assert(!hasRawUnsharedAliasing!(void delegate() shared const));
3053 static assert(!hasRawUnsharedAliasing!(const(void delegate())));
3054 static assert(!hasRawUnsharedAliasing!(const(void delegate() const)));
3055 static assert(!hasRawUnsharedAliasing!(const(void delegate() immutable)));
3056 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared)));
3057 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared const)));
3058 static assert(!hasRawUnsharedAliasing!(immutable(void delegate())));
3059 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() const)));
3060 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() immutable)));
3061 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared)));
3062 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared const)));
3063 static assert(!hasRawUnsharedAliasing!(shared(void delegate())));
3064 static assert(!hasRawUnsharedAliasing!(shared(void delegate() const)));
3065 static assert(!hasRawUnsharedAliasing!(shared(void delegate() immutable)));
3066 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared)));
3067 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared const)));
3068 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate()))));
3069 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() const))));
3070 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() immutable))));
3071 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared))));
3072 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared const))));
3073 static assert(!hasRawUnsharedAliasing!(void function()));
3075 enum S13 { a }
3076 static assert(!hasRawUnsharedAliasing!S13);
3078 // indirect members
3079 struct S14 { S9 a; int b; }
3080 struct S15 { S10 a; int b; }
3081 struct S16 { S6 a; int b; }
3082 static assert( hasRawUnsharedAliasing!S14);
3083 static assert(!hasRawUnsharedAliasing!S15);
3084 static assert(!hasRawUnsharedAliasing!S16);
3086 static assert( hasRawUnsharedAliasing!(int[string]));
3087 static assert(!hasRawUnsharedAliasing!(shared(int[string])));
3088 static assert(!hasRawUnsharedAliasing!(immutable(int[string])));
3090 struct S17
3092 void delegate() shared a;
3093 void delegate() immutable b;
3094 void delegate() shared const c;
3095 shared(void delegate()) d;
3096 shared(void delegate() shared) e;
3097 shared(void delegate() immutable) f;
3098 shared(void delegate() shared const) g;
3099 immutable(void delegate()) h;
3100 immutable(void delegate() shared) i;
3101 immutable(void delegate() immutable) j;
3102 immutable(void delegate() shared const) k;
3103 shared(const(void delegate())) l;
3104 shared(const(void delegate() shared)) m;
3105 shared(const(void delegate() immutable)) n;
3106 shared(const(void delegate() shared const)) o;
3108 struct S18 { typeof(S17.tupleof) a; void delegate() p; }
3109 struct S19 { typeof(S17.tupleof) a; Object p; }
3110 struct S20 { typeof(S17.tupleof) a; int* p; }
3111 class S21 { typeof(S17.tupleof) a; }
3112 class S22 { typeof(S17.tupleof) a; void delegate() p; }
3113 class S23 { typeof(S17.tupleof) a; Object p; }
3114 class S24 { typeof(S17.tupleof) a; int* p; }
3115 static assert(!hasRawUnsharedAliasing!S17);
3116 static assert(!hasRawUnsharedAliasing!(immutable(S17)));
3117 static assert(!hasRawUnsharedAliasing!(shared(S17)));
3118 static assert(!hasRawUnsharedAliasing!S18);
3119 static assert(!hasRawUnsharedAliasing!(immutable(S18)));
3120 static assert(!hasRawUnsharedAliasing!(shared(S18)));
3121 static assert(!hasRawUnsharedAliasing!S19);
3122 static assert(!hasRawUnsharedAliasing!(immutable(S19)));
3123 static assert(!hasRawUnsharedAliasing!(shared(S19)));
3124 static assert( hasRawUnsharedAliasing!S20);
3125 static assert(!hasRawUnsharedAliasing!(immutable(S20)));
3126 static assert(!hasRawUnsharedAliasing!(shared(S20)));
3127 static assert(!hasRawUnsharedAliasing!S21);
3128 static assert(!hasRawUnsharedAliasing!(immutable(S21)));
3129 static assert(!hasRawUnsharedAliasing!(shared(S21)));
3130 static assert(!hasRawUnsharedAliasing!S22);
3131 static assert(!hasRawUnsharedAliasing!(immutable(S22)));
3132 static assert(!hasRawUnsharedAliasing!(shared(S22)));
3133 static assert(!hasRawUnsharedAliasing!S23);
3134 static assert(!hasRawUnsharedAliasing!(immutable(S23)));
3135 static assert(!hasRawUnsharedAliasing!(shared(S23)));
3136 static assert( hasRawUnsharedAliasing!S24);
3137 static assert(!hasRawUnsharedAliasing!(immutable(S24)));
3138 static assert(!hasRawUnsharedAliasing!(shared(S24)));
3139 struct S25 {}
3140 class S26 {}
3141 interface S27 {}
3142 union S28 {}
3143 static assert(!hasRawUnsharedAliasing!S25);
3144 static assert(!hasRawUnsharedAliasing!S26);
3145 static assert(!hasRawUnsharedAliasing!S27);
3146 static assert(!hasRawUnsharedAliasing!S28);
3149 private template hasRawUnsharedAliasingImpl(T)
3151 static if (is(T foo : U*, U) && !isFunctionPointer!T)
3152 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3153 else static if (is(T foo : U[], U) && !isStaticArray!T)
3154 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3155 else static if (isAssociativeArray!T)
3156 enum hasRawUnsharedAliasingImpl = !is(T == immutable) && !is(T == shared);
3157 else
3158 enum hasRawUnsharedAliasingImpl = false;
3162 Statically evaluates to `true` if and only if `T`'s
3163 representation includes at least one non-immutable object reference.
3166 private template hasObjects(T)
3168 static if (is(T == struct))
3170 enum hasObjects = anySatisfy!(.hasObjects, RepresentationTypeTuple!T);
3172 else
3174 enum hasObjects = (is(T == class) || is(T == interface)) && !is(T == immutable);
3179 Statically evaluates to `true` if and only if `T`'s
3180 representation includes at least one non-immutable non-shared object
3181 reference.
3183 private template hasUnsharedObjects(T)
3185 static if (is(T == struct))
3187 enum hasUnsharedObjects = anySatisfy!(.hasUnsharedObjects, RepresentationTypeTuple!T);
3189 else
3191 enum hasUnsharedObjects = (is(T == class) || is(T == interface)) &&
3192 !is(T == immutable) && !is(T == shared);
3197 Returns `true` if and only if `T`'s representation includes at
3198 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3199 is not immutable;) $(LI an array `U[]` and `U` is not
3200 immutable;) $(LI a reference to a class or interface type `C` and `C` is
3201 not immutable.) $(LI an associative array that is not immutable.)
3202 $(LI a delegate.))
3204 template hasAliasing(T...)
3206 enum hasAliasing = anySatisfy!(hasAliasingImpl, T);
3210 @safe unittest
3212 struct S1 { int a; Object b; }
3213 struct S2 { string a; }
3214 struct S3 { int a; immutable Object b; }
3215 struct S4 { float[3] vals; }
3216 static assert( hasAliasing!S1);
3217 static assert(!hasAliasing!S2);
3218 static assert(!hasAliasing!S3);
3219 static assert(!hasAliasing!S4);
3222 @safe unittest
3224 static assert( hasAliasing!(uint[uint]));
3225 static assert(!hasAliasing!(immutable(uint[uint])));
3226 static assert( hasAliasing!(void delegate()));
3227 static assert( hasAliasing!(void delegate() const));
3228 static assert(!hasAliasing!(void delegate() immutable));
3229 static assert( hasAliasing!(void delegate() shared));
3230 static assert( hasAliasing!(void delegate() shared const));
3231 static assert( hasAliasing!(const(void delegate())));
3232 static assert( hasAliasing!(const(void delegate() const)));
3233 static assert(!hasAliasing!(const(void delegate() immutable)));
3234 static assert( hasAliasing!(const(void delegate() shared)));
3235 static assert( hasAliasing!(const(void delegate() shared const)));
3236 static assert(!hasAliasing!(immutable(void delegate())));
3237 static assert(!hasAliasing!(immutable(void delegate() const)));
3238 static assert(!hasAliasing!(immutable(void delegate() immutable)));
3239 static assert(!hasAliasing!(immutable(void delegate() shared)));
3240 static assert(!hasAliasing!(immutable(void delegate() shared const)));
3241 static assert( hasAliasing!(shared(const(void delegate()))));
3242 static assert( hasAliasing!(shared(const(void delegate() const))));
3243 static assert(!hasAliasing!(shared(const(void delegate() immutable))));
3244 static assert( hasAliasing!(shared(const(void delegate() shared))));
3245 static assert( hasAliasing!(shared(const(void delegate() shared const))));
3246 static assert(!hasAliasing!(void function()));
3248 interface I;
3249 static assert( hasAliasing!I);
3251 import std.typecons : Rebindable;
3252 static assert( hasAliasing!(Rebindable!(const Object)));
3253 static assert(!hasAliasing!(Rebindable!(immutable Object)));
3254 static assert( hasAliasing!(Rebindable!(shared Object)));
3255 static assert( hasAliasing!(Rebindable!Object));
3257 struct S5
3259 void delegate() immutable b;
3260 shared(void delegate() immutable) f;
3261 immutable(void delegate() immutable) j;
3262 shared(const(void delegate() immutable)) n;
3264 struct S6 { typeof(S5.tupleof) a; void delegate() p; }
3265 static assert(!hasAliasing!S5);
3266 static assert( hasAliasing!S6);
3268 struct S7 { void delegate() a; int b; Object c; }
3269 class S8 { int a; int b; }
3270 class S9 { typeof(S8.tupleof) a; }
3271 class S10 { typeof(S8.tupleof) a; int* b; }
3272 static assert( hasAliasing!S7);
3273 static assert( hasAliasing!S8);
3274 static assert( hasAliasing!S9);
3275 static assert( hasAliasing!S10);
3276 struct S11 {}
3277 class S12 {}
3278 interface S13 {}
3279 union S14 {}
3280 static assert(!hasAliasing!S11);
3281 static assert( hasAliasing!S12);
3282 static assert( hasAliasing!S13);
3283 static assert(!hasAliasing!S14);
3285 class S15 { S15[1] a; }
3286 static assert( hasAliasing!S15);
3287 static assert(!hasAliasing!(immutable(S15)));
3289 static assert(!hasAliasing!noreturn);
3292 private template hasAliasingImpl(T)
3294 import std.typecons : Rebindable;
3296 static if (is(immutable T == immutable Rebindable!R, R))
3298 enum hasAliasingImpl = hasAliasingImpl!R;
3300 else
3302 template isAliasingDelegate(T)
3304 enum isAliasingDelegate = isDelegate!T
3305 && !is(T == immutable)
3306 && !is(FunctionTypeOf!T == immutable);
3308 enum hasAliasingImpl = hasRawAliasing!T || hasObjects!T ||
3309 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T);
3314 Returns `true` if and only if `T`'s representation includes at
3315 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an
3316 array `U[]`;) $(LI a reference to a class type `C`;)
3317 $(LI an associative array;) $(LI a delegate;)
3318 $(LI a [context pointer][isNested].))
3320 template hasIndirections(T)
3322 import core.internal.traits : _hasIndirections = hasIndirections;
3323 alias hasIndirections = _hasIndirections!T;
3327 @safe unittest
3329 static assert( hasIndirections!(int[string]));
3330 static assert( hasIndirections!(void delegate()));
3331 static assert( hasIndirections!(void delegate() immutable));
3332 static assert( hasIndirections!(immutable(void delegate())));
3333 static assert( hasIndirections!(immutable(void delegate() immutable)));
3335 static assert(!hasIndirections!(void function()));
3336 static assert( hasIndirections!(void*[1]));
3337 static assert(!hasIndirections!(byte[1]));
3340 @safe unittest
3342 // void static array hides actual type of bits, so "may have indirections".
3343 static assert( hasIndirections!(void[1]));
3344 interface I {}
3345 struct S1 {}
3346 struct S2 { int a; }
3347 struct S3 { int a; int b; }
3348 struct S4 { int a; int* b; }
3349 struct S5 { int a; Object b; }
3350 struct S6 { int a; string b; }
3351 struct S7 { int a; immutable Object b; }
3352 struct S8 { int a; immutable I b; }
3353 struct S9 { int a; void delegate() b; }
3354 struct S10 { int a; immutable(void delegate()) b; }
3355 struct S11 { int a; void delegate() immutable b; }
3356 struct S12 { int a; immutable(void delegate() immutable) b; }
3357 class S13 {}
3358 class S14 { int a; }
3359 class S15 { int a; int b; }
3360 class S16 { int a; Object b; }
3361 class S17 { string a; }
3362 class S18 { int a; immutable Object b; }
3363 class S19 { int a; immutable(void delegate() immutable) b; }
3364 union S20 {}
3365 union S21 { int a; }
3366 union S22 { int a; int b; }
3367 union S23 { int a; Object b; }
3368 union S24 { string a; }
3369 union S25 { int a; immutable Object b; }
3370 union S26 { int a; immutable(void delegate() immutable) b; }
3371 static assert( hasIndirections!I);
3372 static assert(!hasIndirections!S1);
3373 static assert(!hasIndirections!S2);
3374 static assert(!hasIndirections!S3);
3375 static assert( hasIndirections!S4);
3376 static assert( hasIndirections!S5);
3377 static assert( hasIndirections!S6);
3378 static assert( hasIndirections!S7);
3379 static assert( hasIndirections!S8);
3380 static assert( hasIndirections!S9);
3381 static assert( hasIndirections!S10);
3382 static assert( hasIndirections!S12);
3383 static assert( hasIndirections!S13);
3384 static assert( hasIndirections!S14);
3385 static assert( hasIndirections!S15);
3386 static assert( hasIndirections!S16);
3387 static assert( hasIndirections!S17);
3388 static assert( hasIndirections!S18);
3389 static assert( hasIndirections!S19);
3390 static assert(!hasIndirections!S20);
3391 static assert(!hasIndirections!S21);
3392 static assert(!hasIndirections!S22);
3393 static assert( hasIndirections!S23);
3394 static assert( hasIndirections!S24);
3395 static assert( hasIndirections!S25);
3396 static assert( hasIndirections!S26);
3397 int local;
3398 struct HasContextPointer { int opCall() { return ++local; } }
3399 static assert(hasIndirections!HasContextPointer);
3401 static assert(!hasIndirections!noreturn);
3404 // https://issues.dlang.org/show_bug.cgi?id=12000
3405 @safe unittest
3407 static struct S(T)
3409 static assert(hasIndirections!T);
3412 static class A(T)
3414 S!A a;
3417 A!int dummy;
3421 Returns `true` if and only if `T`'s representation includes at
3422 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3423 is not immutable or shared;) $(LI an array `U[]` and `U` is not
3424 immutable or shared;) $(LI a reference to a class type `C` and
3425 `C` is not immutable or shared.) $(LI an associative array that is not
3426 immutable or shared.) $(LI a delegate that is not shared.))
3429 template hasUnsharedAliasing(T...)
3431 enum hasUnsharedAliasing = anySatisfy!(hasUnsharedAliasingImpl, T);
3435 @safe unittest
3437 struct S1 { int a; Object b; }
3438 struct S2 { string a; }
3439 struct S3 { int a; immutable Object b; }
3440 static assert( hasUnsharedAliasing!S1);
3441 static assert(!hasUnsharedAliasing!S2);
3442 static assert(!hasUnsharedAliasing!S3);
3444 struct S4 { int a; shared Object b; }
3445 struct S5 { char[] a; }
3446 struct S6 { shared char[] b; }
3447 struct S7 { float[3] vals; }
3448 static assert(!hasUnsharedAliasing!S4);
3449 static assert( hasUnsharedAliasing!S5);
3450 static assert(!hasUnsharedAliasing!S6);
3451 static assert(!hasUnsharedAliasing!S7);
3454 @safe unittest
3456 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
3457 import std.typecons : Rebindable;
3458 struct S8 { int a; Rebindable!(immutable Object) b; }
3459 static assert(!hasUnsharedAliasing!S8);
3461 static assert( hasUnsharedAliasing!(uint[uint]));
3463 static assert( hasUnsharedAliasing!(void delegate()));
3464 static assert( hasUnsharedAliasing!(void delegate() const));
3465 static assert(!hasUnsharedAliasing!(void delegate() immutable));
3466 static assert(!hasUnsharedAliasing!(void delegate() shared));
3467 static assert(!hasUnsharedAliasing!(void delegate() shared const));
3470 @safe unittest
3472 import std.typecons : Rebindable;
3473 static assert( hasUnsharedAliasing!(const(void delegate())));
3474 static assert( hasUnsharedAliasing!(const(void delegate() const)));
3475 static assert(!hasUnsharedAliasing!(const(void delegate() immutable)));
3476 static assert(!hasUnsharedAliasing!(const(void delegate() shared)));
3477 static assert(!hasUnsharedAliasing!(const(void delegate() shared const)));
3478 static assert(!hasUnsharedAliasing!(immutable(void delegate())));
3479 static assert(!hasUnsharedAliasing!(immutable(void delegate() const)));
3480 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable)));
3481 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared)));
3482 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const)));
3483 static assert(!hasUnsharedAliasing!(shared(void delegate())));
3484 static assert(!hasUnsharedAliasing!(shared(void delegate() const)));
3485 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable)));
3486 static assert(!hasUnsharedAliasing!(shared(void delegate() shared)));
3487 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const)));
3488 static assert(!hasUnsharedAliasing!(shared(const(void delegate()))));
3489 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const))));
3490 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable))));
3491 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared))));
3492 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const))));
3493 static assert(!hasUnsharedAliasing!(void function()));
3495 interface I {}
3496 static assert(hasUnsharedAliasing!I);
3498 static assert( hasUnsharedAliasing!(Rebindable!(const Object)));
3499 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object)));
3500 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object)));
3501 static assert( hasUnsharedAliasing!(Rebindable!Object));
3503 /* https://issues.dlang.org/show_bug.cgi?id=6979 */
3504 static assert(!hasUnsharedAliasing!(int, shared(int)*));
3505 static assert( hasUnsharedAliasing!(int, int*));
3506 static assert( hasUnsharedAliasing!(int, const(int)[]));
3507 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object));
3508 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object)));
3509 static assert(!hasUnsharedAliasing!());
3511 struct S9
3513 void delegate() shared a;
3514 void delegate() immutable b;
3515 void delegate() shared const c;
3516 shared(void delegate()) d;
3517 shared(void delegate() shared) e;
3518 shared(void delegate() immutable) f;
3519 shared(void delegate() shared const) g;
3520 immutable(void delegate()) h;
3521 immutable(void delegate() shared) i;
3522 immutable(void delegate() immutable) j;
3523 immutable(void delegate() shared const) k;
3524 shared(const(void delegate())) l;
3525 shared(const(void delegate() shared)) m;
3526 shared(const(void delegate() immutable)) n;
3527 shared(const(void delegate() shared const)) o;
3529 struct S10 { typeof(S9.tupleof) a; void delegate() p; }
3530 struct S11 { typeof(S9.tupleof) a; Object p; }
3531 struct S12 { typeof(S9.tupleof) a; int* p; }
3532 class S13 { typeof(S9.tupleof) a; }
3533 class S14 { typeof(S9.tupleof) a; void delegate() p; }
3534 class S15 { typeof(S9.tupleof) a; Object p; }
3535 class S16 { typeof(S9.tupleof) a; int* p; }
3536 static assert(!hasUnsharedAliasing!S9);
3537 static assert(!hasUnsharedAliasing!(immutable(S9)));
3538 static assert(!hasUnsharedAliasing!(shared(S9)));
3539 static assert( hasUnsharedAliasing!S10);
3540 static assert(!hasUnsharedAliasing!(immutable(S10)));
3541 static assert(!hasUnsharedAliasing!(shared(S10)));
3542 static assert( hasUnsharedAliasing!S11);
3543 static assert(!hasUnsharedAliasing!(immutable(S11)));
3544 static assert(!hasUnsharedAliasing!(shared(S11)));
3545 static assert( hasUnsharedAliasing!S12);
3546 static assert(!hasUnsharedAliasing!(immutable(S12)));
3547 static assert(!hasUnsharedAliasing!(shared(S12)));
3548 static assert( hasUnsharedAliasing!S13);
3549 static assert(!hasUnsharedAliasing!(immutable(S13)));
3550 static assert(!hasUnsharedAliasing!(shared(S13)));
3551 static assert( hasUnsharedAliasing!S14);
3552 static assert(!hasUnsharedAliasing!(immutable(S14)));
3553 static assert(!hasUnsharedAliasing!(shared(S14)));
3554 static assert( hasUnsharedAliasing!S15);
3555 static assert(!hasUnsharedAliasing!(immutable(S15)));
3556 static assert(!hasUnsharedAliasing!(shared(S15)));
3557 static assert( hasUnsharedAliasing!S16);
3558 static assert(!hasUnsharedAliasing!(immutable(S16)));
3559 static assert(!hasUnsharedAliasing!(shared(S16)));
3560 struct S17 {}
3561 class S18 {}
3562 interface S19 {}
3563 union S20 {}
3564 static assert(!hasUnsharedAliasing!S17);
3565 static assert( hasUnsharedAliasing!S18);
3566 static assert( hasUnsharedAliasing!S19);
3567 static assert(!hasUnsharedAliasing!S20);
3569 static assert(!hasUnsharedAliasing!noreturn);
3572 private template hasUnsharedAliasingImpl(T)
3574 import std.typecons : Rebindable;
3576 static if (is(immutable T == immutable Rebindable!R, R))
3578 enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R;
3580 else
3582 template unsharedDelegate(T)
3584 enum bool unsharedDelegate = isDelegate!T
3585 && !is(T == shared)
3586 && !is(T == immutable)
3587 && !is(FunctionTypeOf!T == shared)
3588 && !is(FunctionTypeOf!T == immutable);
3591 enum hasUnsharedAliasingImpl =
3592 hasRawUnsharedAliasing!T ||
3593 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!T) ||
3594 hasUnsharedObjects!T;
3598 version (StdDdoc)
3601 True if `S` or any type embedded directly in the representation of `S`
3602 defines an elaborate copy constructor. Elaborate copy constructors are
3603 introduced by defining `this(this)` for a `struct`.
3605 Classes and unions never have elaborate copy constructors.
3607 template hasElaborateCopyConstructor(S)
3609 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3610 alias hasElaborateCopyConstructor = hasElabCCtor!(S);
3613 else
3615 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3616 alias hasElaborateCopyConstructor = hasElabCCtor;
3620 @safe unittest
3622 static assert(!hasElaborateCopyConstructor!int);
3624 static struct S1 { }
3625 static struct S2 { this(this) {} }
3626 static struct S3 { S2 field; }
3627 static struct S4 { S3[1] field; }
3628 static struct S5 { S3[] field; }
3629 static struct S6 { S3[0] field; }
3630 static struct S7 { @disable this(); S3 field; }
3631 static assert(!hasElaborateCopyConstructor!S1);
3632 static assert( hasElaborateCopyConstructor!S2);
3633 static assert( hasElaborateCopyConstructor!(immutable S2));
3634 static assert( hasElaborateCopyConstructor!S3);
3635 static assert( hasElaborateCopyConstructor!(S3[1]));
3636 static assert(!hasElaborateCopyConstructor!(S3[0]));
3637 static assert( hasElaborateCopyConstructor!S4);
3638 static assert(!hasElaborateCopyConstructor!S5);
3639 static assert(!hasElaborateCopyConstructor!S6);
3640 static assert( hasElaborateCopyConstructor!S7);
3644 True if `S` or any type directly embedded in the representation of `S`
3645 defines an elaborate assignment. Elaborate assignments are introduced by
3646 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this)))
3647 for a `struct` or when there is a compiler-generated `opAssign`.
3649 A type `S` gets compiler-generated `opAssign` if it has
3650 an elaborate destructor.
3652 Classes and unions never have elaborate assignments.
3654 Note: Structs with (possibly nested) postblit operator(s) will have a
3655 hidden yet elaborate compiler generated assignment operator (unless
3656 explicitly disabled).
3658 template hasElaborateAssign(S)
3660 static if (isStaticArray!S && S.length)
3662 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0]));
3664 else static if (is(S == struct))
3666 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
3667 is(typeof(S.init.opAssign(lvalueOf!S))) ||
3668 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S);
3670 else
3672 enum bool hasElaborateAssign = false;
3677 @safe unittest
3679 static assert(!hasElaborateAssign!int);
3681 static struct S { void opAssign(S) {} }
3682 static assert( hasElaborateAssign!S);
3683 static assert(!hasElaborateAssign!(const(S)));
3685 static struct S1 { void opAssign(ref S1) {} }
3686 static struct S2 { void opAssign(int) {} }
3687 static struct S3 { S s; }
3688 static assert( hasElaborateAssign!S1);
3689 static assert(!hasElaborateAssign!S2);
3690 static assert( hasElaborateAssign!S3);
3691 static assert( hasElaborateAssign!(S3[1]));
3692 static assert(!hasElaborateAssign!(S3[0]));
3695 @safe unittest
3697 static struct S { void opAssign(S) {} }
3698 static struct S4
3700 void opAssign(U)(U u) {}
3701 @disable void opAssign(U)(ref U u);
3703 static assert( hasElaborateAssign!S4);
3705 static struct S41
3707 void opAssign(U)(ref U u) {}
3708 @disable void opAssign(U)(U u);
3710 static assert( hasElaborateAssign!S41);
3712 static struct S5 { @disable this(); this(int n){ s = S(); } S s; }
3713 static assert( hasElaborateAssign!S5);
3715 static struct S6 { this(this) {} }
3716 static struct S7 { this(this) {} @disable void opAssign(S7); }
3717 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} }
3718 static struct S9 { this(this) {} void opAssign(int) {} }
3719 static struct S10 { ~this() { } }
3720 static assert( hasElaborateAssign!S6);
3721 static assert(!hasElaborateAssign!S7);
3722 static assert(!hasElaborateAssign!S8);
3723 static assert( hasElaborateAssign!S9);
3724 static assert( hasElaborateAssign!S10);
3725 static struct SS6 { S6 s; }
3726 static struct SS7 { S7 s; }
3727 static struct SS8 { S8 s; }
3728 static struct SS9 { S9 s; }
3729 static assert( hasElaborateAssign!SS6);
3730 static assert(!hasElaborateAssign!SS7);
3731 static assert(!hasElaborateAssign!SS8);
3732 static assert( hasElaborateAssign!SS9);
3735 version (StdDdoc)
3738 True if `S` or any type directly embedded in the representation
3739 of `S` defines an elaborate destructor. Elaborate destructors
3740 are introduced by defining `~this()` for a $(D
3741 struct).
3743 Classes and unions never have elaborate destructors, even
3744 though classes may define `~this()`.
3746 template hasElaborateDestructor(S)
3748 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3749 alias hasElaborateDestructor = hasElabDest!(S);
3752 else
3754 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3755 alias hasElaborateDestructor = hasElabDest;
3759 @safe unittest
3761 static assert(!hasElaborateDestructor!int);
3763 static struct S1 { }
3764 static struct S2 { ~this() {} }
3765 static struct S3 { S2 field; }
3766 static struct S4 { S3[1] field; }
3767 static struct S5 { S3[] field; }
3768 static struct S6 { S3[0] field; }
3769 static struct S7 { @disable this(); S3 field; }
3770 static assert(!hasElaborateDestructor!S1);
3771 static assert( hasElaborateDestructor!S2);
3772 static assert( hasElaborateDestructor!(immutable S2));
3773 static assert( hasElaborateDestructor!S3);
3774 static assert( hasElaborateDestructor!(S3[1]));
3775 static assert(!hasElaborateDestructor!(S3[0]));
3776 static assert( hasElaborateDestructor!S4);
3777 static assert(!hasElaborateDestructor!S5);
3778 static assert(!hasElaborateDestructor!S6);
3779 static assert( hasElaborateDestructor!S7);
3782 version (StdDdoc)
3785 True if `S` or any type embedded directly in the representation of `S`
3786 defines elaborate move semantics. Elaborate move semantics are
3787 introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
3789 Classes and unions never have elaborate move semantics.
3791 template hasElaborateMove(S)
3793 import core.internal.traits : hasElabMove = hasElaborateMove;
3794 alias hasElaborateMove = hasElabMove!(S);
3797 else
3799 import core.internal.traits : hasElabMove = hasElaborateMove;
3800 alias hasElaborateMove = hasElabMove;
3804 @safe unittest
3806 static assert(!hasElaborateMove!int);
3808 static struct S1 { }
3809 static struct S2 { void opPostMove(ref S2) {} }
3810 static struct S3 { void opPostMove(inout ref S3) inout {} }
3811 static struct S4 { void opPostMove(const ref S4) {} }
3812 static struct S5 { void opPostMove(S5) {} }
3813 static struct S6 { void opPostMove(int) {} }
3814 static struct S7 { S3[1] field; }
3815 static struct S8 { S3[] field; }
3816 static struct S9 { S3[0] field; }
3817 static struct S10 { @disable this(); S3 field; }
3818 static assert(!hasElaborateMove!S1);
3819 static assert( hasElaborateMove!S2);
3820 static assert( hasElaborateMove!S3);
3821 static assert( hasElaborateMove!(immutable S3));
3822 static assert( hasElaborateMove!S4);
3823 static assert(!hasElaborateMove!S5);
3824 static assert(!hasElaborateMove!S6);
3825 static assert( hasElaborateMove!S7);
3826 static assert(!hasElaborateMove!S8);
3827 static assert(!hasElaborateMove!S9);
3828 static assert( hasElaborateMove!S10);
3831 package alias Identity(alias A) = A;
3834 Yields `true` if and only if `T` is an aggregate that defines
3835 a symbol called `name`.
3837 See also: $(DDSUBLINK spec/traits, hasMember, `__traits(hasMember, T, name)`)
3839 enum hasMember(T, string name) = __traits(hasMember, T, name);
3842 @safe unittest
3844 static assert(!hasMember!(int, "blah"));
3845 struct S1 { int blah; }
3846 struct S2 { int blah(){ return 0; } }
3847 class C1 { int blah; }
3848 class C2 { int blah(){ return 0; } }
3849 static assert(hasMember!(S1, "blah"));
3850 static assert(hasMember!(S2, "blah"));
3851 static assert(hasMember!(C1, "blah"));
3852 static assert(hasMember!(C2, "blah"));
3855 @safe unittest
3857 // https://issues.dlang.org/show_bug.cgi?id=8321
3858 struct S {
3859 int x;
3860 void f(){}
3861 void t()(){}
3862 template T(){}
3864 struct R1(T) {
3865 T t;
3866 alias t this;
3868 struct R2(T) {
3869 T t;
3870 @property ref inout(T) payload() inout { return t; }
3871 alias t this;
3873 static assert(hasMember!(S, "x"));
3874 static assert(hasMember!(S, "f"));
3875 static assert(hasMember!(S, "t"));
3876 static assert(hasMember!(S, "T"));
3877 static assert(hasMember!(R1!S, "x"));
3878 static assert(hasMember!(R1!S, "f"));
3879 static assert(hasMember!(R1!S, "t"));
3880 static assert(hasMember!(R1!S, "T"));
3881 static assert(hasMember!(R2!S, "x"));
3882 static assert(hasMember!(R2!S, "f"));
3883 static assert(hasMember!(R2!S, "t"));
3884 static assert(hasMember!(R2!S, "T"));
3887 @safe unittest
3889 static struct S
3891 void opDispatch(string n, A)(A dummy) {}
3893 static assert(hasMember!(S, "foo"));
3897 * Whether the symbol represented by the string, member, exists and is a static member of T.
3899 * Params:
3900 * T = Type containing symbol `member`.
3901 * member = Name of symbol to test that resides in `T`.
3903 * Returns:
3904 * `true` iff `member` exists and is static.
3906 template hasStaticMember(T, string member)
3908 static if (__traits(hasMember, T, member))
3910 static if (is(T == V*, V))
3911 alias U = V;
3912 else
3913 alias U = T;
3915 import std.meta : Alias;
3916 alias sym = Alias!(__traits(getMember, U, member));
3918 static if (__traits(getOverloads, U, member).length == 0)
3919 enum bool hasStaticMember = __traits(compiles, &sym);
3920 else
3921 enum bool hasStaticMember = __traits(isStaticFunction, sym);
3923 else
3925 enum bool hasStaticMember = false;
3930 @safe unittest
3932 static struct S
3934 static void sf() {}
3935 void f() {}
3937 static int si;
3938 int i;
3941 static assert( hasStaticMember!(S, "sf"));
3942 static assert(!hasStaticMember!(S, "f"));
3944 static assert( hasStaticMember!(S, "si"));
3945 static assert(!hasStaticMember!(S, "i"));
3947 static assert(!hasStaticMember!(S, "hello"));
3950 @safe unittest
3952 static struct S
3954 enum X = 10;
3955 enum Y
3957 i = 10
3959 struct S {}
3960 class C {}
3962 static int sx = 0;
3963 __gshared int gx = 0;
3965 Y y;
3966 static Y sy;
3968 static void f();
3969 static void f2() pure nothrow @nogc @safe;
3971 void g() shared;
3973 static void function() fp;
3974 __gshared void function() gfp;
3975 void function() fpm;
3977 void delegate() dm;
3978 static void delegate() sd;
3980 void m();
3981 void m2() const pure nothrow @nogc @safe;
3983 inout(int) iom() inout;
3984 static inout(int) iosf(inout int x);
3986 @property int p();
3987 static @property int sp();
3990 static class C
3992 enum X = 10;
3993 enum Y
3995 i = 10
3997 struct S {}
3998 class C {}
4000 static int sx = 0;
4001 __gshared int gx = 0;
4003 Y y;
4004 static Y sy;
4006 static void f();
4007 static void f2() pure nothrow @nogc @safe;
4009 void g() shared { }
4011 static void function() fp;
4012 __gshared void function() gfp;
4013 void function() fpm;
4015 void delegate() dm;
4016 static void delegate() sd;
4018 void m() {}
4019 final void m2() const pure nothrow @nogc @safe;
4021 inout(int) iom() inout { return 10; }
4022 static inout(int) iosf(inout int x);
4024 @property int p() { return 10; }
4025 static @property int sp();
4028 static assert(!hasStaticMember!(S, "na"));
4029 static assert(!hasStaticMember!(S, "X"));
4030 static assert(!hasStaticMember!(S, "Y"));
4031 static assert(!hasStaticMember!(S, "Y.i"));
4032 static assert(!hasStaticMember!(S, "S"));
4033 static assert(!hasStaticMember!(S, "C"));
4034 static assert( hasStaticMember!(S, "sx"));
4035 static assert( hasStaticMember!(S, "gx"));
4036 static assert(!hasStaticMember!(S, "y"));
4037 static assert( hasStaticMember!(S, "sy"));
4038 static assert( hasStaticMember!(S, "f"));
4039 static assert( hasStaticMember!(S, "f2"));
4040 static assert(!hasStaticMember!(S, "dm"));
4041 static assert( hasStaticMember!(S, "sd"));
4042 static assert(!hasStaticMember!(S, "g"));
4043 static assert( hasStaticMember!(S, "fp"));
4044 static assert( hasStaticMember!(S, "gfp"));
4045 static assert(!hasStaticMember!(S, "fpm"));
4046 static assert(!hasStaticMember!(S, "m"));
4047 static assert(!hasStaticMember!(S, "m2"));
4048 static assert(!hasStaticMember!(S, "iom"));
4049 static assert( hasStaticMember!(S, "iosf"));
4050 static assert(!hasStaticMember!(S, "p"));
4051 static assert( hasStaticMember!(S, "sp"));
4053 static assert(!hasStaticMember!(C, "na"));
4054 static assert(!hasStaticMember!(C, "X"));
4055 static assert(!hasStaticMember!(C, "Y"));
4056 static assert(!hasStaticMember!(C, "Y.i"));
4057 static assert(!hasStaticMember!(C, "S"));
4058 static assert(!hasStaticMember!(C, "C"));
4059 static assert( hasStaticMember!(C, "sx"));
4060 static assert( hasStaticMember!(C, "gx"));
4061 static assert(!hasStaticMember!(C, "y"));
4062 static assert( hasStaticMember!(C, "sy"));
4063 static assert( hasStaticMember!(C, "f"));
4064 static assert( hasStaticMember!(C, "f2"));
4065 static assert(!hasStaticMember!(C, "dm"));
4066 static assert( hasStaticMember!(C, "sd"));
4067 static assert(!hasStaticMember!(C, "g"));
4068 static assert( hasStaticMember!(C, "fp"));
4069 static assert( hasStaticMember!(C, "gfp"));
4070 static assert(!hasStaticMember!(C, "fpm"));
4071 static assert(!hasStaticMember!(C, "m"));
4072 static assert(!hasStaticMember!(C, "m2"));
4073 static assert(!hasStaticMember!(C, "iom"));
4074 static assert( hasStaticMember!(C, "iosf"));
4075 static assert(!hasStaticMember!(C, "p"));
4076 static assert( hasStaticMember!(C, "sp"));
4078 alias P = S*;
4079 static assert(!hasStaticMember!(P, "na"));
4080 static assert(!hasStaticMember!(P, "X"));
4081 static assert(!hasStaticMember!(P, "Y"));
4082 static assert(!hasStaticMember!(P, "Y.i"));
4083 static assert(!hasStaticMember!(P, "S"));
4084 static assert(!hasStaticMember!(P, "C"));
4085 static assert( hasStaticMember!(P, "sx"));
4086 static assert( hasStaticMember!(P, "gx"));
4087 static assert(!hasStaticMember!(P, "y"));
4088 static assert( hasStaticMember!(P, "sy"));
4089 static assert( hasStaticMember!(P, "f"));
4090 static assert( hasStaticMember!(P, "f2"));
4091 static assert(!hasStaticMember!(P, "dm"));
4092 static assert( hasStaticMember!(P, "sd"));
4093 static assert(!hasStaticMember!(P, "g"));
4094 static assert( hasStaticMember!(P, "fp"));
4095 static assert( hasStaticMember!(P, "gfp"));
4096 static assert(!hasStaticMember!(P, "fpm"));
4097 static assert(!hasStaticMember!(P, "m"));
4098 static assert(!hasStaticMember!(P, "m2"));
4099 static assert(!hasStaticMember!(P, "iom"));
4100 static assert( hasStaticMember!(P, "iosf"));
4101 static assert(!hasStaticMember!(P, "p"));
4102 static assert( hasStaticMember!(P, "sp"));
4106 Retrieves the members of an enumerated type `enum E`.
4108 Params:
4109 E = An enumerated type. `E` may have duplicated values.
4111 Returns:
4112 Static tuple composed of the members of the enumerated type `E`.
4113 The members are arranged in the same order as declared in `E`.
4114 The name of the enum can be found by querying the compiler for the
4115 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`.
4116 For enumerations with unique values, $(REF to, std,conv) can also be used.
4118 Note:
4119 An enum can have multiple members which have the same value. If you want
4120 to use EnumMembers to e.g. generate switch cases at compile-time,
4121 you should use the $(REF NoDuplicates, std,meta) template to avoid
4122 generating duplicate switch cases.
4124 Note:
4125 Returned values are strictly typed with `E`. Thus, the following code
4126 does not work without the explicit cast:
4127 --------------------
4128 enum E : int { a, b, c }
4129 int[] abc = cast(int[]) [ EnumMembers!E ];
4130 --------------------
4131 Cast is not necessary if the type of the variable is inferred. See the
4132 example below.
4134 template EnumMembers(E)
4135 if (is(E == enum))
4137 alias EnumMembers = AliasSeq!();
4138 static foreach (M; __traits(allMembers, E))
4139 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, M));
4142 /// Create an array of enumerated values
4143 @safe unittest
4145 enum Sqrts : real
4147 one = 1,
4148 two = 1.41421,
4149 three = 1.73205
4151 auto sqrts = [EnumMembers!Sqrts];
4152 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
4156 A generic function `rank(v)` in the following example uses this
4157 template for finding a member `e` in an enumerated type `E`.
4159 @safe unittest
4161 // Returns i if e is the i-th enumerator of E.
4162 static size_t rank(E)(E e)
4163 if (is(E == enum))
4165 static foreach (i, member; EnumMembers!E)
4167 if (e == member)
4168 return i;
4170 assert(0, "Not an enum member");
4173 enum Mode
4175 read = 1,
4176 write = 2,
4177 map = 4
4179 assert(rank(Mode.read) == 0);
4180 assert(rank(Mode.write) == 1);
4181 assert(rank(Mode.map) == 2);
4185 Use EnumMembers to generate a switch statement using static foreach.
4188 @safe unittest
4190 import std.conv : to;
4191 class FooClass
4193 string calledMethod;
4194 void foo() @safe { calledMethod = "foo"; }
4195 void bar() @safe { calledMethod = "bar"; }
4196 void baz() @safe { calledMethod = "baz"; }
4199 enum FooEnum { foo, bar, baz }
4201 auto var = FooEnum.bar;
4202 auto fooObj = new FooClass();
4203 s: final switch (var)
4205 static foreach (member; EnumMembers!FooEnum)
4207 case member: // Generate a case for each enum value.
4208 // Call fooObj.{name of enum value}().
4209 __traits(getMember, fooObj, to!string(member))();
4210 break s;
4213 // As we pass in FooEnum.bar, the bar() method gets called.
4214 assert(fooObj.calledMethod == "bar");
4217 @safe unittest
4219 enum A { a }
4220 static assert([ EnumMembers!A ] == [ A.a ]);
4221 enum B { a, b, c, d, e }
4222 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]);
4225 @safe unittest // typed enums
4227 enum A : string { a = "alpha", b = "beta" }
4228 static assert([ EnumMembers!A ] == [ A.a, A.b ]);
4230 static struct S
4232 int value;
4233 int opCmp(S rhs) const nothrow { return value - rhs.value; }
4235 enum B : S { a = S(1), b = S(2), c = S(3) }
4236 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]);
4239 @safe unittest // duplicated values
4241 enum A
4243 a = 0, b = 0,
4244 c = 1, d = 1, e
4246 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]);
4249 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
4250 @safe unittest
4252 string genEnum()
4254 string result = "enum TLAs {";
4255 foreach (c0; '0'..'2'+1)
4256 foreach (c1; '0'..'9'+1)
4257 foreach (c2; '0'..'9'+1)
4258 foreach (c3; '0'..'9'+1)
4260 result ~= '_';
4261 result ~= c0;
4262 result ~= c1;
4263 result ~= c2;
4264 result ~= c3;
4265 result ~= ',';
4267 result ~= '}';
4268 return result;
4270 mixin(genEnum);
4271 static assert(EnumMembers!TLAs[0] == TLAs._0000);
4272 static assert(EnumMembers!TLAs[$-1] == TLAs._2999);
4275 @safe unittest
4277 enum E { member, a = 0, b = 0 }
4278 static assert(__traits(identifier, EnumMembers!E[0]) == "member");
4279 static assert(__traits(identifier, EnumMembers!E[1]) == "a");
4280 static assert(__traits(identifier, EnumMembers!E[2]) == "b");
4284 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4285 // Classes and Interfaces
4286 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4288 /***
4289 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
4290 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
4291 * the empty type tuple.
4293 template BaseTypeTuple(A)
4295 static if (is(A P == super))
4296 alias BaseTypeTuple = P;
4297 else
4298 static assert(0, "argument is not a class or interface");
4302 @safe unittest
4304 import std.meta : AliasSeq;
4306 interface I1 { }
4307 interface I2 { }
4308 interface I12 : I1, I2 { }
4309 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));
4311 interface I3 : I1 { }
4312 interface I123 : I1, I2, I3 { }
4313 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));
4316 @safe unittest
4318 interface I1 { }
4319 interface I2 { }
4320 class A { }
4321 class C : A, I1, I2 { }
4323 alias TL = BaseTypeTuple!C;
4324 assert(TL.length == 3);
4325 assert(is (TL[0] == A));
4326 assert(is (TL[1] == I1));
4327 assert(is (TL[2] == I2));
4329 assert(BaseTypeTuple!Object.length == 0);
4333 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4334 * in decreasing order. Interfaces are not included. $(D_PARAM
4335 * BaseClassesTuple!Object) yields the empty type tuple.
4337 template BaseClassesTuple(T)
4338 if (is(T == class))
4340 static if (is(T == Object))
4342 alias BaseClassesTuple = AliasSeq!();
4344 else static if (is(BaseTypeTuple!T[0] == Object))
4346 alias BaseClassesTuple = AliasSeq!Object;
4348 else static if (!is(BaseTypeTuple!T[0] == Object) && !is(BaseTypeTuple!T[0] == class))
4350 alias BaseClassesTuple = AliasSeq!();
4352 else
4354 alias BaseClassesTuple =
4355 AliasSeq!(BaseTypeTuple!T[0],
4356 BaseClassesTuple!(BaseTypeTuple!T[0]));
4361 @safe unittest
4363 import std.meta : AliasSeq;
4365 class C1 { }
4366 class C2 : C1 { }
4367 class C3 : C2 { }
4368 static assert(!BaseClassesTuple!Object.length);
4369 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
4370 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
4371 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));
4374 // https://issues.dlang.org/show_bug.cgi?id=17276
4375 @safe unittest
4377 extern (C++) static interface Ext
4379 void someext();
4382 extern (C++) static class E : Ext
4384 void someext() {}
4387 alias BaseClassesWithNoObject = BaseClassesTuple!E;
4390 @safe unittest
4392 struct S { }
4393 static assert(!__traits(compiles, BaseClassesTuple!S));
4394 interface I { }
4395 static assert(!__traits(compiles, BaseClassesTuple!I));
4396 class C4 : I { }
4397 class C5 : C4, I { }
4398 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object)));
4402 Params:
4403 T = The `class` or `interface` to search.
4405 Returns:
4406 $(REF AliasSeq,std,meta) of all interfaces directly or
4407 indirectly inherited by this class or interface. Interfaces
4408 do not repeat if multiply implemented.
4410 `InterfacesTuple!Object` yields an empty `AliasSeq`.
4412 template InterfacesTuple(T)
4414 import std.meta : NoDuplicates;
4415 template Flatten(H, T...)
4417 static if (T.length)
4419 alias Flatten = AliasSeq!(Flatten!H, Flatten!T);
4421 else
4423 static if (is(H == interface))
4424 alias Flatten = AliasSeq!(H, InterfacesTuple!H);
4425 else
4426 alias Flatten = InterfacesTuple!H;
4430 static if (is(T S == super) && S.length)
4431 alias InterfacesTuple = NoDuplicates!(Flatten!S);
4432 else
4433 alias InterfacesTuple = AliasSeq!();
4437 @safe unittest
4439 interface I1 {}
4440 interface I2 {}
4441 class A : I1, I2 {}
4442 class B : A, I1 {}
4443 class C : B {}
4445 alias TL = InterfacesTuple!C;
4446 static assert(is(TL[0] == I1) && is(TL[1] == I2));
4449 @safe unittest
4451 interface Iaa {}
4452 interface Iab {}
4453 interface Iba {}
4454 interface Ibb {}
4455 interface Ia : Iaa, Iab {}
4456 interface Ib : Iba, Ibb {}
4457 interface I : Ia, Ib {}
4458 interface J {}
4459 class B2 : J {}
4460 class C2 : B2, Ia, Ib {}
4461 static assert(is(InterfacesTuple!I ==
4462 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb)));
4463 static assert(is(InterfacesTuple!C2 ==
4464 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb)));
4469 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4470 * T), in decreasing order, followed by $(D_PARAM T)'s
4471 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4472 * empty type tuple.
4474 alias TransitiveBaseTypeTuple(T) = AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
4477 @safe unittest
4479 interface J1 {}
4480 interface J2 {}
4481 class B1 {}
4482 class B2 : B1, J1, J2 {}
4483 class B3 : B2, J1 {}
4484 alias TL = TransitiveBaseTypeTuple!B3;
4485 assert(TL.length == 5);
4486 assert(is (TL[0] == B2));
4487 assert(is (TL[1] == B1));
4488 assert(is (TL[2] == Object));
4489 assert(is (TL[3] == J1));
4490 assert(is (TL[4] == J2));
4492 assert(TransitiveBaseTypeTuple!Object.length == 0);
4497 Returns a tuple of non-static functions with the name `name` declared in the
4498 class or interface `C`. Covariant duplicates are shrunk into the most
4499 derived one.
4501 template MemberFunctionsTuple(C, string name)
4502 if (is(C == class) || is(C == interface))
4504 static if (__traits(hasMember, C, name))
4507 * First, collect all overloads in the class hierarchy.
4509 template CollectOverloads(Node)
4511 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
4513 // Get all overloads in sight (not hidden).
4514 alias inSight = __traits(getVirtualMethods, Node, name);
4516 // And collect all overloads in ancestor classes to reveal hidden
4517 // methods. The result may contain duplicates.
4518 template walkThru(Parents...)
4520 static if (Parents.length > 0)
4521 alias walkThru = AliasSeq!(
4522 CollectOverloads!(Parents[0]),
4523 walkThru!(Parents[1 .. $])
4525 else
4526 alias walkThru = AliasSeq!();
4529 static if (is(Node Parents == super))
4530 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents);
4531 else
4532 alias CollectOverloads = AliasSeq!inSight;
4534 else
4535 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy
4538 static if (name == "__ctor" || name == "__dtor")
4539 alias overloads = AliasSeq!(__traits(getOverloads, C, name));
4540 else
4541 // duplicates in this tuple will be removed by shrink()
4542 alias overloads = CollectOverloads!C;
4544 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4545 // shrinkOne!args[1..$] = non-covariant others
4546 template shrinkOne(/+ alias target, rest... +/ args...)
4548 import std.meta : AliasSeq;
4549 alias target = args[0 .. 1]; // prevent property functions from being evaluated
4550 alias rest = args[1 .. $];
4552 static if (rest.length > 0)
4554 alias Target = FunctionTypeOf!target;
4555 alias Rest0 = FunctionTypeOf!(rest[0]);
4557 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target))
4559 // One of these overrides the other. Choose the one from the most derived parent.
4560 static if (is(__traits(parent, target) : __traits(parent, rest[0])))
4561 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4562 else
4563 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4565 else static if (isCovariantWith!(Target, Rest0))
4566 // target overrides rest[0] -- erase rest[0].
4567 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4568 else static if (isCovariantWith!(Rest0, Target))
4569 // rest[0] overrides target -- erase target.
4570 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4571 else
4572 // target and rest[0] are distinct.
4573 alias shrinkOne = AliasSeq!(
4574 shrinkOne!(target, rest[1 .. $]),
4575 rest[0] // keep
4578 else
4579 alias shrinkOne = AliasSeq!target; // done
4583 * Now shrink covariant overloads into one.
4585 template shrink(overloads...)
4587 static if (overloads.length > 0)
4589 alias temp = shrinkOne!overloads;
4590 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $]));
4592 else
4593 alias shrink = AliasSeq!(); // done
4596 // done.
4597 alias MemberFunctionsTuple = shrink!overloads;
4599 else
4600 alias MemberFunctionsTuple = AliasSeq!();
4604 @safe unittest
4606 interface I { I foo(); }
4607 class B
4609 real foo(real v) { return v; }
4611 class C : B, I
4613 override C foo() { return this; } // covariant overriding of I.foo()
4615 alias foos = MemberFunctionsTuple!(C, "foo");
4616 static assert(foos.length == 2);
4617 static assert(__traits(isSame, foos[0], C.foo));
4618 static assert(__traits(isSame, foos[1], B.foo));
4621 // https://issues.dlang.org/show_bug.cgi?id=15920
4622 @safe unittest
4624 import std.meta : AliasSeq;
4625 class A
4627 void f(){}
4628 void f(int){}
4630 class B : A
4632 override void f(){}
4633 override void f(int){}
4635 alias fs = MemberFunctionsTuple!(B, "f");
4636 alias bfs = __traits(getOverloads, B, "f");
4637 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1]));
4638 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1]));
4641 // https://issues.dlang.org/show_bug.cgi?id=8388
4642 @safe unittest
4644 class C
4646 this() {}
4647 this(int i) {}
4648 this(int i, float j) {}
4649 this(string s) {}
4652 Commented out, because this causes a cyclic dependency
4653 between module constructors/destructors error. Might
4654 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */
4655 // static this() {}
4657 ~this() {}
4660 class D : C
4662 this() {}
4663 ~this() {}
4666 alias test_ctor = MemberFunctionsTuple!(C, "__ctor");
4667 assert(test_ctor.length == 4);
4668 alias test_dtor = MemberFunctionsTuple!(C, "__dtor");
4669 assert(test_dtor.length == 1);
4670 alias test2_ctor = MemberFunctionsTuple!(D, "__ctor");
4671 assert(test2_ctor.length == 1);
4672 alias test2_dtor = MemberFunctionsTuple!(D, "__dtor");
4673 assert(test2_dtor.length == 1);
4676 @safe unittest
4678 interface I { I test(); }
4679 interface J : I { J test(); }
4680 interface K { K test(int); }
4681 class B : I, K
4683 K test(int) { return this; }
4684 B test() { return this; }
4685 static void test(string) { }
4687 class C : B, J
4689 override C test() { return this; }
4691 alias test =MemberFunctionsTuple!(C, "test");
4692 static assert(test.length == 2);
4693 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test)));
4694 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test)));
4695 alias noexist = MemberFunctionsTuple!(C, "noexist");
4696 static assert(noexist.length == 0);
4698 interface L { int prop() @property; }
4699 alias prop = MemberFunctionsTuple!(L, "prop");
4700 static assert(prop.length == 1);
4702 interface Test_I
4704 void foo();
4705 void foo(int);
4706 void foo(int, int);
4708 interface Test : Test_I {}
4709 alias Test_foo = MemberFunctionsTuple!(Test, "foo");
4710 static assert(Test_foo.length == 3);
4711 static assert(is(typeof(&Test_foo[0]) == void function()));
4712 static assert(is(typeof(&Test_foo[2]) == void function(int)));
4713 static assert(is(typeof(&Test_foo[1]) == void function(int, int)));
4718 Returns an alias to the template that `T` is an instance of.
4719 It will return `void` if a symbol without a template is given.
4721 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
4723 /// ditto
4724 alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
4726 /// ditto
4727 alias TemplateOf(T) = void;
4730 @safe unittest
4732 struct Foo(T, U) {}
4733 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4736 @safe unittest
4738 template Foo1(A) {}
4739 template Foo2(A, B) {}
4740 template Foo3(alias A) {}
4741 template Foo4(string A) {}
4742 struct Foo5(A) {}
4743 struct Foo6(A, B) {}
4744 struct Foo7(alias A) {}
4745 template Foo8(A) { template Foo9(B) {} }
4746 template Foo10() {}
4748 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4749 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4750 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4751 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4752 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4753 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4754 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4755 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4756 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4759 // https://issues.dlang.org/show_bug.cgi?id=18214
4760 @safe unittest
4762 static assert(is(TemplateOf!(int[]) == void));
4763 static assert(is(TemplateOf!bool == void));
4767 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4769 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4771 /// ditto
4772 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4775 @safe unittest
4777 import std.meta : AliasSeq;
4779 struct Foo(T, U) {}
4780 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4783 @safe unittest
4785 template Foo1(A) {}
4786 template Foo2(A, B) {}
4787 template Foo3(alias A) {}
4788 template Foo4(string A) {}
4789 struct Foo5(A) {}
4790 struct Foo6(A, B) {}
4791 struct Foo7(alias A) {}
4792 template Foo8(A) { template Foo9(B) {} }
4793 template Foo10() {}
4795 enum x = 123;
4796 enum y = "123";
4797 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4798 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4799 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4800 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4801 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4802 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4803 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4804 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4805 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4808 // Returns the largest alignment in a type tuple.
4809 package enum maxAlignment(U...) =
4811 size_t result = U[0].alignof;
4812 static foreach (T; U[1 .. $])
4813 if (result < T.alignof)
4814 result = T.alignof;
4815 return result;
4816 }();
4819 Returns class instance alignment.
4821 See also: $(DDSUBLINK spec/traits, classInstanceAlignment, `__traits(classInstanceAlignment, T)`)
4823 template classInstanceAlignment(T)
4824 if (is(T == class))
4826 enum classInstanceAlignment = __traits(classInstanceAlignment, T);
4830 @safe unittest
4832 class A { byte b; }
4833 class B { long l; }
4835 // As class instance always has a hidden pointer
4836 static assert(classInstanceAlignment!A == (void*).alignof);
4837 static assert(classInstanceAlignment!B == long.alignof);
4841 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4842 // Type Conversion
4843 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4846 Get the type that all types can be implicitly converted to. Useful
4847 e.g. in figuring out an array type from a bunch of initializing
4848 values. Returns $(D_PARAM void) if passed an empty list, or if the
4849 types have no common type.
4851 template CommonType(T...)
4853 static if (T.length == 1)
4854 alias CommonType = typeof(T[0].init);
4855 else static if (is(typeof(true ? T[0].init : T[1].init) U))
4856 alias CommonType = CommonType!(U, T[2 .. $]);
4857 else
4858 alias CommonType = void;
4862 @safe unittest
4864 alias X = CommonType!(int, long, short);
4865 assert(is(X == long));
4866 alias Y = CommonType!(int, char[], short);
4867 assert(is(Y == void));
4871 @safe unittest
4873 static assert(is(CommonType!(3) == int));
4874 static assert(is(CommonType!(double, 4, float) == double));
4875 static assert(is(CommonType!(string, char[]) == const(char)[]));
4876 static assert(is(CommonType!(3, 3U) == uint));
4877 static assert(is(CommonType!(double, int) == double));
4882 Params:
4883 T = The type to check
4885 Returns:
4886 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4887 conversion `T`.
4889 If `T` is a class derived from `Object`, the result of
4890 $(LREF TransitiveBaseTypeTuple) is returned.
4892 If the type is not a built-in value type or a class derived from
4893 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4895 See_Also:
4896 $(LREF isImplicitlyConvertible)
4898 template AllImplicitConversionTargets(T)
4900 static if (is(T == bool))
4901 alias AllImplicitConversionTargets =
4902 AliasSeq!(byte, AllImplicitConversionTargets!byte);
4903 else static if (is(T == byte))
4904 alias AllImplicitConversionTargets =
4905 AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4906 else static if (is(T == ubyte))
4907 alias AllImplicitConversionTargets =
4908 AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4909 else static if (is(T == short))
4910 alias AllImplicitConversionTargets =
4911 AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4912 else static if (is(T == ushort))
4913 alias AllImplicitConversionTargets =
4914 AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4915 else static if (is(T == int))
4916 alias AllImplicitConversionTargets =
4917 AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4918 else static if (is(T == uint))
4919 alias AllImplicitConversionTargets =
4920 AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4921 else static if (is(T == long))
4922 alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4923 else static if (is(T == ulong))
4924 alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4925 else static if (is(T == float))
4926 alias AllImplicitConversionTargets = AliasSeq!(double, real);
4927 else static if (is(T == double))
4928 alias AllImplicitConversionTargets = AliasSeq!(float, real);
4929 else static if (is(T == real))
4930 alias AllImplicitConversionTargets = AliasSeq!(float, double);
4931 else static if (is(T == char))
4932 alias AllImplicitConversionTargets =
4933 AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4934 else static if (is(T == wchar))
4935 alias AllImplicitConversionTargets =
4936 AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4937 else static if (is(T == dchar))
4938 alias AllImplicitConversionTargets =
4939 AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4940 else static if (is(T == class))
4941 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4942 else static if (is(T == interface))
4943 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4944 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4946 static if (is(typeof(T.init[0]) == shared))
4947 alias AllImplicitConversionTargets =
4948 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4949 else
4950 alias AllImplicitConversionTargets =
4951 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4953 else static if (is(T : void*) && !is(T == void*))
4954 alias AllImplicitConversionTargets = AliasSeq!(void*);
4955 else static if (is(cent) && is(T == cent))
4956 alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4957 else static if (is(ucent) && is(T == ucent))
4958 alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4959 else
4960 alias AllImplicitConversionTargets = AliasSeq!();
4964 @safe unittest
4966 import std.meta : AliasSeq;
4968 static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4969 static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4970 static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4971 static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4973 static assert(is(AllImplicitConversionTargets!(char) ==
4974 AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4975 ulong, float, double, real)
4977 static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4978 short, ushort, dchar, int, uint, long, ulong, float, double, real
4979 )));
4980 static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
4981 int, uint, long, ulong, float, double, real
4982 )));
4984 static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
4985 static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
4987 interface A {}
4988 interface B {}
4989 class C : A, B {}
4991 static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
4992 static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
4993 static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
4994 immutable Object, immutable A, immutable B
4995 )));
4997 interface I : A, B {}
4999 static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
5000 static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
5001 static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
5002 immutable A, immutable B
5003 )));
5006 @safe unittest
5008 static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5009 static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5010 static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5015 Params:
5016 T = The type to check
5018 Warning:
5019 This template is considered out-dated. It will be removed from
5020 Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5022 Returns:
5023 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5024 conversion `T`.
5026 If `T` is a class derived from `Object`, the result of
5027 $(LREF TransitiveBaseTypeTuple) is returned.
5029 If the type is not a built-in value type or a class derived from
5030 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5032 Note:
5033 The possible targets are computed more conservatively than the
5034 language allows, eliminating all dangerous conversions. For example,
5035 `ImplicitConversionTargets!double` does not include `float`.
5037 See_Also:
5038 $(LREF isImplicitlyConvertible)
5040 // @@@DEPRECATED_[2.107.0]@@@
5041 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5042 ~ "and will be removed in 2.107.0")
5043 template ImplicitConversionTargets(T)
5045 static if (is(T == bool))
5046 alias ImplicitConversionTargets =
5047 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5048 float, double, real, char, wchar, dchar);
5049 else static if (is(T == byte))
5050 alias ImplicitConversionTargets =
5051 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5052 float, double, real, char, wchar, dchar);
5053 else static if (is(T == ubyte))
5054 alias ImplicitConversionTargets =
5055 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5056 float, double, real, char, wchar, dchar);
5057 else static if (is(T == short))
5058 alias ImplicitConversionTargets =
5059 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5060 else static if (is(T == ushort))
5061 alias ImplicitConversionTargets =
5062 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5063 else static if (is(T == int))
5064 alias ImplicitConversionTargets =
5065 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5066 else static if (is(T == uint))
5067 alias ImplicitConversionTargets =
5068 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5069 else static if (is(T == long))
5070 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5071 else static if (is(T == ulong))
5072 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5073 else static if (is(cent) && is(T == cent))
5074 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5075 else static if (is(ucent) && is(T == ucent))
5076 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5077 else static if (is(T == float))
5078 alias ImplicitConversionTargets = AliasSeq!(double, real);
5079 else static if (is(T == double))
5080 alias ImplicitConversionTargets = AliasSeq!real;
5081 else static if (is(T == char))
5082 alias ImplicitConversionTargets =
5083 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5084 int, uint, long, ulong, CentTypeList, float, double, real);
5085 else static if (is(T == wchar))
5086 alias ImplicitConversionTargets =
5087 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5088 float, double, real);
5089 else static if (is(T == dchar))
5090 alias ImplicitConversionTargets =
5091 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5092 else static if (is(T : typeof(null)))
5093 alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5094 else static if (is(T == class))
5095 alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5096 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5098 static if (is(typeof(T.init[0]) == shared))
5099 alias ImplicitConversionTargets =
5100 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5101 else
5102 alias ImplicitConversionTargets =
5103 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5105 else static if (is(T : void*))
5106 alias ImplicitConversionTargets = AliasSeq!(void*);
5107 else
5108 alias ImplicitConversionTargets = AliasSeq!();
5111 deprecated @safe unittest
5113 import std.meta : AliasSeq;
5115 static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5116 static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5117 static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5118 static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5120 static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5121 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5122 )));
5123 static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5124 dchar, short, ushort, int, uint, long, ulong, float, double, real
5125 )));
5126 static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5127 int, uint, long, ulong, float, double, real
5128 )));
5130 static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5131 static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5133 interface A {}
5134 interface B {}
5135 class C : A, B {}
5137 static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5138 static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5139 static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5140 immutable Object, immutable A, immutable B
5141 )));
5144 deprecated @safe unittest
5146 static assert(is(ImplicitConversionTargets!(double)[0] == real));
5147 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5151 Is `From` implicitly convertible to `To`?
5153 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5156 @safe unittest
5158 static assert( isImplicitlyConvertible!(immutable(char), char));
5159 static assert( isImplicitlyConvertible!(const(char), char));
5160 static assert( isImplicitlyConvertible!(char, wchar));
5161 static assert(!isImplicitlyConvertible!(wchar, char));
5163 static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5164 static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5165 static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5167 static assert(!isImplicitlyConvertible!(const(char)[], string));
5168 static assert( isImplicitlyConvertible!(string, const(char)[]));
5172 Is `From` $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) to `To`?
5174 enum bool isQualifierConvertible(From, To) =
5175 is(immutable From == immutable To) && is(From* : To*);
5178 @safe unittest
5180 // Mutable and immmutable both convert to const...
5181 static assert( isQualifierConvertible!(char, const(char)));
5182 static assert( isQualifierConvertible!(immutable(char), const(char)));
5183 // ...but const does not convert back to mutable or immutable
5184 static assert(!isQualifierConvertible!(const(char), char));
5185 static assert(!isQualifierConvertible!(const(char), immutable(char)));
5188 @safe unittest
5190 import std.meta : AliasSeq;
5192 alias Ts = AliasSeq!(int, const int, shared int, inout int, const shared int,
5193 const inout int, inout shared int, const inout shared int, immutable int);
5195 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
5196 enum _ = 0;
5197 static immutable bool[Ts.length][Ts.length] conversions = [
5198 // m c s i cs ci is cis im
5199 [1, 1, _, _, _, _, _, _, _], // mutable
5200 [_, 1, _, _, _, _, _, _, _], // const
5201 [_, _, 1, _, 1, _, _, _, _], // shared
5202 [_, 1, _, 1, _, 1, _, _, _], // inout
5203 [_, _, _, _, 1, _, _, _, _], // const shared
5204 [_, 1, _, _, _, 1, _, _, _], // const inout
5205 [_, _, _, _, 1, _, 1, 1, _], // inout shared
5206 [_, _, _, _, 1, _, _, 1, _], // const inout shared
5207 [_, 1, _, _, 1, 1, _, 1, 1], // immutable
5210 static foreach (i, From; Ts)
5212 static foreach (j, To; Ts)
5214 static assert(isQualifierConvertible!(From, To) == conversions[i][j],
5215 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`"
5216 ~ " should be `" ~ (conversions[i][j] ? "true" : "false") ~ "`");
5221 @safe unittest
5223 // int* -> void* is not a qualifier conversion
5224 static assert(!isQualifierConvertible!(int, void));
5228 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5229 type `Lhs`.
5231 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5233 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5235 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5238 @safe unittest
5240 static assert( isAssignable!(long, int));
5241 static assert(!isAssignable!(int, long));
5242 static assert( isAssignable!(const(char)[], string));
5243 static assert(!isAssignable!(string, char[]));
5245 // int is assignable to int
5246 static assert( isAssignable!int);
5248 // immutable int is not assignable to immutable int
5249 static assert(!isAssignable!(immutable int));
5253 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5254 type `Lhs`.
5256 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5259 @safe unittest
5261 struct S1
5263 void opAssign(S1);
5266 struct S2
5268 void opAssign(ref S2);
5271 static assert( isRvalueAssignable!(long, int));
5272 static assert(!isRvalueAssignable!(int, long));
5273 static assert( isRvalueAssignable!S1);
5274 static assert(!isRvalueAssignable!S2);
5278 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5279 type `Lhs`.
5281 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5284 @safe unittest
5286 struct S1
5288 void opAssign(S1);
5291 struct S2
5293 void opAssign(ref S2);
5296 static assert( isLvalueAssignable!(long, int));
5297 static assert(!isLvalueAssignable!(int, long));
5298 static assert( isLvalueAssignable!S1);
5299 static assert( isLvalueAssignable!S2);
5302 @safe unittest
5304 static assert(!isAssignable!(immutable int, int));
5305 static assert( isAssignable!(int, immutable int));
5307 static assert(!isAssignable!(inout int, int));
5308 static assert( isAssignable!(int, inout int));
5309 static assert(!isAssignable!(inout int));
5311 static assert( isAssignable!(shared int, int));
5312 static assert( isAssignable!(int, shared int));
5313 static assert( isAssignable!(shared int));
5315 static assert( isAssignable!(void[1], void[1]));
5317 struct S { @disable this(); this(int n){} }
5318 static assert( isAssignable!(S, S));
5320 struct S2 { this(int n){} }
5321 static assert( isAssignable!(S2, S2));
5322 static assert(!isAssignable!(S2, int));
5324 struct S3 { @disable void opAssign(); }
5325 static assert( isAssignable!(S3, S3));
5327 struct S3X { @disable void opAssign(S3X); }
5328 static assert(!isAssignable!(S3X, S3X));
5330 struct S4 { void opAssign(int); }
5331 static assert( isAssignable!(S4, S4));
5332 static assert( isAssignable!(S4, int));
5333 static assert( isAssignable!(S4, immutable int));
5335 struct S5 { @disable this(); @disable this(this); }
5336 // https://issues.dlang.org/show_bug.cgi?id=21210
5337 static assert(!isAssignable!S5);
5339 // `-preview=in` is enabled
5340 alias DScannerBug895 = int[256];
5341 static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
5343 struct S6 { void opAssign(in S5); }
5345 static assert(isRvalueAssignable!(S6, S5));
5346 static assert(isLvalueAssignable!(S6, S5));
5347 static assert(isAssignable!(S6, S5));
5348 static assert(isAssignable!(S6, immutable S5));
5350 else
5352 mixin(q{ struct S6 { void opAssign(scope const ref S5); } });
5354 static assert(!isRvalueAssignable!(S6, S5));
5355 static assert( isLvalueAssignable!(S6, S5));
5356 static assert(!isAssignable!(S6, S5));
5357 static assert( isLvalueAssignable!(S6, immutable S5));
5362 // Equivalent with TypeStruct::isAssignable in compiler code.
5363 package template isBlitAssignable(T)
5365 static if (is(T == enum))
5367 enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5369 else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5370 // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary.
5372 enum isBlitAssignable = isBlitAssignable!E;
5374 else static if (is(T == struct) || is(T == union))
5376 enum isBlitAssignable = isMutable!T &&
5378 size_t offset = 0;
5379 bool assignable = true;
5380 foreach (i, F; FieldTypeTuple!T)
5382 static if (i == 0)
5385 else
5387 if (T.tupleof[i].offsetof == offset)
5389 if (assignable)
5390 continue;
5392 else
5394 if (!assignable)
5395 return false;
5398 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5399 offset = T.tupleof[i].offsetof;
5401 return assignable;
5402 }();
5404 else
5405 enum isBlitAssignable = isMutable!T;
5408 @safe unittest
5410 static assert( isBlitAssignable!int);
5411 static assert(!isBlitAssignable!(const int));
5413 class C{ const int i; }
5414 static assert( isBlitAssignable!C);
5416 struct S1{ int i; }
5417 struct S2{ const int i; }
5418 static assert( isBlitAssignable!S1);
5419 static assert(!isBlitAssignable!S2);
5421 struct S3X { union { int x; int y; } }
5422 struct S3Y { union { int x; const int y; } }
5423 struct S3Z { union { const int x; const int y; } }
5424 static assert( isBlitAssignable!(S3X));
5425 static assert( isBlitAssignable!(S3Y));
5426 static assert(!isBlitAssignable!(S3Z));
5427 static assert(!isBlitAssignable!(const S3X));
5428 static assert(!isBlitAssignable!(inout S3Y));
5429 static assert(!isBlitAssignable!(immutable S3Z));
5430 static assert( isBlitAssignable!(S3X[3]));
5431 static assert( isBlitAssignable!(S3Y[3]));
5432 static assert(!isBlitAssignable!(S3Z[3]));
5433 enum ES3X : S3X { a = S3X() }
5434 enum ES3Y : S3Y { a = S3Y() }
5435 enum ES3Z : S3Z { a = S3Z() }
5436 static assert( isBlitAssignable!(ES3X));
5437 static assert( isBlitAssignable!(ES3Y));
5438 static assert(!isBlitAssignable!(ES3Z));
5439 static assert(!isBlitAssignable!(const ES3X));
5440 static assert(!isBlitAssignable!(inout ES3Y));
5441 static assert(!isBlitAssignable!(immutable ES3Z));
5442 static assert( isBlitAssignable!(ES3X[3]));
5443 static assert( isBlitAssignable!(ES3Y[3]));
5444 static assert(!isBlitAssignable!(ES3Z[3]));
5446 union U1X { int x; int y; }
5447 union U1Y { int x; const int y; }
5448 union U1Z { const int x; const int y; }
5449 static assert( isBlitAssignable!(U1X));
5450 static assert( isBlitAssignable!(U1Y));
5451 static assert(!isBlitAssignable!(U1Z));
5452 static assert(!isBlitAssignable!(const U1X));
5453 static assert(!isBlitAssignable!(inout U1Y));
5454 static assert(!isBlitAssignable!(immutable U1Z));
5455 static assert( isBlitAssignable!(U1X[3]));
5456 static assert( isBlitAssignable!(U1Y[3]));
5457 static assert(!isBlitAssignable!(U1Z[3]));
5458 enum EU1X : U1X { a = U1X() }
5459 enum EU1Y : U1Y { a = U1Y() }
5460 enum EU1Z : U1Z { a = U1Z() }
5461 static assert( isBlitAssignable!(EU1X));
5462 static assert( isBlitAssignable!(EU1Y));
5463 static assert(!isBlitAssignable!(EU1Z));
5464 static assert(!isBlitAssignable!(const EU1X));
5465 static assert(!isBlitAssignable!(inout EU1Y));
5466 static assert(!isBlitAssignable!(immutable EU1Z));
5467 static assert( isBlitAssignable!(EU1X[3]));
5468 static assert( isBlitAssignable!(EU1Y[3]));
5469 static assert(!isBlitAssignable!(EU1Z[3]));
5471 struct SA
5473 @property int[3] foo() { return [1,2,3]; }
5474 alias foo this;
5475 const int x; // SA is not blit assignable
5477 static assert(!isStaticArray!SA);
5478 static assert(!isBlitAssignable!(SA[3]));
5483 Works like `isImplicitlyConvertible`, except this cares only about storage
5484 classes of the arguments.
5486 private template isStorageClassImplicitlyConvertible(From, To)
5488 alias Pointify(T) = void*;
5490 enum isStorageClassImplicitlyConvertible = is(
5491 ModifyTypePreservingTQ!(Pointify, From) :
5492 ModifyTypePreservingTQ!(Pointify, To) );
5495 @safe unittest
5497 static assert( isStorageClassImplicitlyConvertible!( int, const int));
5498 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5500 static assert(!isStorageClassImplicitlyConvertible!(const int, int));
5501 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5502 static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5503 static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5508 Determines whether the function type `F` is covariant with `G`, i.e.,
5509 functions of the type `F` can override ones of the type `G`.
5511 template isCovariantWith(F, G)
5512 if (is(F == function) && is(G == function) ||
5513 is(F == delegate) && is(G == delegate) ||
5514 isFunctionPointer!F && isFunctionPointer!G)
5516 static if (is(F : G))
5517 enum isCovariantWith = true;
5518 else
5520 alias Upr = F;
5521 alias Lwr = G;
5524 * Check for calling convention: require exact match.
5526 template checkLinkage()
5528 enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5531 * Check for variadic parameter: require exact match.
5533 template checkVariadicity()
5535 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5538 * Check for function storage class:
5539 * - overrider can have narrower storage class than base
5541 template checkSTC()
5543 // Note the order of arguments. The convertion order Lwr -> Upr is
5544 // correct since Upr should be semantically 'narrower' than Lwr.
5545 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5548 * Check for function attributes:
5549 * - require exact match for ref and @property
5550 * - overrider can add pure and nothrow, but can't remove them
5551 * - @safe and @trusted are covariant with each other, unremovable
5553 template checkAttributes()
5555 alias FA = FunctionAttribute;
5556 enum uprAtts = functionAttributes!Upr;
5557 enum lwrAtts = functionAttributes!Lwr;
5559 enum wantExact = FA.ref_ | FA.property;
5560 enum safety = FA.safe | FA.trusted;
5561 enum ok =
5562 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) &&
5563 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) &&
5564 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5565 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ;
5568 * Check for return type: usual implicit convertion.
5570 template checkReturnType()
5572 enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5575 * Check for parameters:
5576 * - require exact match for types
5577 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5578 * - require exact match for in, out, ref and lazy
5579 * - overrider can add scope, but can't remove
5581 template checkParameters()
5583 alias STC = ParameterStorageClass;
5584 alias UprParams = Parameters!Upr;
5585 alias LwrParams = Parameters!Lwr;
5586 alias UprPSTCs = ParameterStorageClassTuple!Upr;
5587 alias LwrPSTCs = ParameterStorageClassTuple!Lwr;
5589 template checkNext(size_t i)
5591 static if (i < UprParams.length)
5593 enum uprStc = UprPSTCs[i];
5594 enum lwrStc = LwrPSTCs[i];
5596 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5597 enum ok =
5598 ((uprStc & wantExact ) == (lwrStc & wantExact )) &&
5599 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) &&
5600 checkNext!(i + 1).ok;
5602 else
5603 enum ok = true; // done
5605 static if (UprParams.length == LwrParams.length)
5606 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5607 else
5608 enum ok = false;
5611 /* run all the checks */
5612 enum isCovariantWith =
5613 checkLinkage !().ok &&
5614 checkVariadicity!().ok &&
5615 checkSTC !().ok &&
5616 checkAttributes !().ok &&
5617 checkReturnType !().ok &&
5618 checkParameters !().ok ;
5623 @safe unittest
5625 interface I { I clone(); }
5626 interface J { J clone(); }
5627 class C : I
5629 override C clone() // covariant overriding of I.clone()
5631 return new C;
5635 // C.clone() can override I.clone(), indeed.
5636 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5638 // C.clone() can't override J.clone(); the return type C is not implicitly
5639 // convertible to J.
5640 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5643 @safe unittest
5645 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5647 // covariant return type
5648 interface I {}
5649 interface J : I {}
5650 interface BaseA { const(I) test(int); }
5651 interface DerivA_1 : BaseA { override const(J) test(int); }
5652 interface DerivA_2 : BaseA { override J test(int); }
5653 static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5654 static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5655 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5656 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5657 static assert( isCovariantWith!(BaseA.test, BaseA.test));
5658 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5659 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5661 // function, function pointer and delegate
5662 J function() derived_function;
5663 I function() base_function;
5664 J delegate() derived_delegate;
5665 I delegate() base_delegate;
5666 static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5667 static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5668 static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5670 // scope parameter
5671 interface BaseB { void test( int*, int*); }
5672 interface DerivB_1 : BaseB { override void test(scope int*, int*); }
5673 interface DerivB_2 : BaseB { override void test( int*, scope int*); }
5674 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5675 static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5676 static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5677 static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5678 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5679 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5680 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5682 // function storage class
5683 interface BaseC { void test() ; }
5684 interface DerivC_1 : BaseC { override void test() const; }
5685 static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5686 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5688 // increasing safety
5689 interface BaseE { void test() ; }
5690 interface DerivE_1 : BaseE { override void test() @safe ; }
5691 interface DerivE_2 : BaseE { override void test() @trusted; }
5692 static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5693 static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5694 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5695 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5697 // @safe and @trusted
5698 interface BaseF
5700 void test1() @safe;
5701 void test2() @trusted;
5703 interface DerivF : BaseF
5705 override void test1() @trusted;
5706 override void test2() @safe;
5708 static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5709 static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5713 // Needed for rvalueOf/lvalueOf because "inout on return means
5714 // inout must be on a parameter as well"
5715 private struct __InoutWorkaroundStruct{}
5718 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5719 $(DDSUBLINK spec/traits, compiles, `__traits(compiles, ...)`) purposes. No actual value is returned.
5721 Params:
5722 T = The type to transform
5724 Note: Trying to use returned value will result in a
5725 "Symbol Undefined" error at link time.
5727 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5729 /// ditto
5730 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5732 // Note: can't put these unittests together as function overloads
5733 // aren't allowed inside functions.
5735 @system unittest
5737 static int f(int);
5738 static assert(is(typeof(f(rvalueOf!int)) == int));
5742 @system unittest
5744 static bool f(ref int);
5745 static assert(is(typeof(f(lvalueOf!int)) == bool));
5748 @system unittest
5750 void needLvalue(T)(ref T);
5751 static struct S { }
5752 int i;
5753 struct Nested { void f() { ++i; } }
5754 static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5756 static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5757 static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5758 static assert(is(typeof(rvalueOf!T) == T));
5759 static assert(is(typeof(lvalueOf!T) == T));
5762 static assert(!__traits(compiles, rvalueOf!int = 1));
5763 static assert( __traits(compiles, lvalueOf!byte = 127));
5764 static assert(!__traits(compiles, lvalueOf!byte = 128));
5768 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5769 // SomethingTypeOf
5770 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5774 template BooleanTypeOf(T)
5776 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5777 alias X = BooleanTypeOf!AT;
5778 else
5779 alias X = OriginalType!T;
5781 static if (is(immutable X == immutable bool))
5783 alias BooleanTypeOf = X;
5785 else
5786 static assert(0, T.stringof~" is not boolean type");
5789 @safe unittest
5791 // unexpected failure, maybe dmd type-merging bug
5792 static foreach (T; AliasSeq!bool)
5793 static foreach (Q; TypeQualifierList)
5795 static assert( is(Q!T == BooleanTypeOf!( Q!T )));
5796 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5799 static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5800 static foreach (Q; TypeQualifierList)
5802 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof);
5803 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5807 @safe unittest
5809 struct B
5811 bool val;
5812 alias val this;
5814 struct S
5816 B b;
5817 alias b this;
5819 static assert(is(BooleanTypeOf!B == bool));
5820 static assert(is(BooleanTypeOf!S == bool));
5825 template IntegralTypeOf(T)
5827 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5828 alias X = IntegralTypeOf!AT;
5829 else
5830 alias X = OriginalType!T;
5832 static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5833 && !is(immutable X == immutable bool) && !is(X == __vector))
5835 alias IntegralTypeOf = X;
5837 else
5838 static assert(0, T.stringof~" is not an integral type");
5841 @safe unittest
5843 static foreach (T; IntegralTypeList)
5844 static foreach (Q; TypeQualifierList)
5846 static assert( is(Q!T == IntegralTypeOf!( Q!T )));
5847 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5850 static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5851 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5852 static foreach (Q; TypeQualifierList)
5854 static assert(!is(IntegralTypeOf!( Q!T )));
5855 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5861 template FloatingPointTypeOf(T)
5863 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5864 alias X = FloatingPointTypeOf!AT;
5865 else
5866 alias X = OriginalType!T;
5868 static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5870 alias FloatingPointTypeOf = X;
5872 else
5873 static assert(0, T.stringof~" is not a floating point type");
5876 @safe unittest
5878 static foreach (T; FloatingPointTypeList)
5879 static foreach (Q; TypeQualifierList)
5881 static assert( is(Q!T == FloatingPointTypeOf!( Q!T )));
5882 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5885 static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5886 static foreach (Q; TypeQualifierList)
5888 static assert(!is(FloatingPointTypeOf!( Q!T )));
5889 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5895 template NumericTypeOf(T)
5897 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5899 alias NumericTypeOf = X;
5901 else
5902 static assert(0, T.stringof~" is not a numeric type");
5905 @safe unittest
5907 static foreach (T; NumericTypeList)
5908 static foreach (Q; TypeQualifierList)
5910 static assert( is(Q!T == NumericTypeOf!( Q!T )));
5911 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5914 static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5915 static foreach (Q; TypeQualifierList)
5917 static assert(!is(NumericTypeOf!( Q!T )));
5918 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5924 template UnsignedTypeOf(T)
5926 static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5927 alias UnsignedTypeOf = X;
5928 else
5929 static assert(0, T.stringof~" is not an unsigned type.");
5934 template SignedTypeOf(T)
5936 static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5937 alias SignedTypeOf = X;
5938 else static if (is(FloatingPointTypeOf!T X))
5939 alias SignedTypeOf = X;
5940 else
5941 static assert(0, T.stringof~" is not an signed type.");
5946 template CharTypeOf(T)
5948 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5949 alias X = CharTypeOf!AT;
5950 else
5951 alias X = OriginalType!T;
5953 static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5955 alias CharTypeOf = X;
5957 else
5958 static assert(0, T.stringof~" is not a character type");
5961 @safe unittest
5963 static foreach (T; CharTypeList)
5964 static foreach (Q; TypeQualifierList)
5966 static assert( is(CharTypeOf!( Q!T )));
5967 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5970 static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
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!(string, wstring, dstring, char[4]))
5978 static foreach (Q; TypeQualifierList)
5980 static assert(!is(CharTypeOf!( Q!T )));
5981 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5987 template StaticArrayTypeOf(T)
5989 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5990 alias X = StaticArrayTypeOf!AT;
5991 else
5992 alias X = OriginalType!T;
5994 static if (__traits(isStaticArray, X))
5995 alias StaticArrayTypeOf = X;
5996 else
5997 static assert(0, T.stringof~" is not a static array type");
6000 @safe unittest
6002 static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6003 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6005 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) ));
6007 static foreach (P; TypeQualifierList)
6008 { // SubTypeOf cannot have inout type
6009 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
6013 static foreach (T; AliasSeq!void)
6014 static foreach (Q; AliasSeq!TypeQualifierList)
6016 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
6022 template DynamicArrayTypeOf(T)
6024 import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
6025 alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
6028 @safe unittest
6030 import std.meta : Alias;
6031 static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6032 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6034 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) ));
6035 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) ));
6037 static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
6039 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
6040 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
6044 static assert(!is(DynamicArrayTypeOf!(int[3])));
6045 static assert(!is(DynamicArrayTypeOf!(void[3])));
6046 static assert(!is(DynamicArrayTypeOf!(typeof(null))));
6051 template ArrayTypeOf(T)
6053 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
6055 alias ArrayTypeOf = X;
6057 else
6058 static assert(0, T.stringof~" is not an array type");
6062 * Converts strings and string-like types to the corresponding dynamic array of characters.
6063 * Params:
6064 * T = one of the following:
6065 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6066 * (`shared` is rejected)
6067 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6068 * (`shared` is rejected)
6069 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6071 * Other cases are rejected with a compile time error.
6072 * `typeof(null)` is rejected.
6074 * Returns:
6075 * The result of `[]` applied to the qualified character type.
6077 template StringTypeOf(T)
6079 static if (is(T == typeof(null)))
6081 // It is impossible to determine exact string type from typeof(null) -
6082 // it means that StringTypeOf!(typeof(null)) is undefined.
6083 // Then this behavior is convenient for template constraint.
6084 static assert(0, T.stringof~" is not a string type");
6086 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
6088 static if (is(T : U[], U))
6089 alias StringTypeOf = U[];
6090 else
6091 static assert(0);
6093 else
6094 static assert(0, T.stringof~" is not a string type");
6097 @safe unittest
6099 import std.meta : Alias;
6100 static foreach (T; CharTypeList)
6101 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6103 static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6105 static if (!__traits(isSame, Q, InoutOf))
6107 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6109 alias Str = Q!T[];
6110 struct C(S) { S val; alias val this; }
6111 static assert(is(StringTypeOf!(C!Str) == Str));
6115 static foreach (T; CharTypeList)
6116 static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6118 static assert(!is(StringTypeOf!( Q!T[] )));
6122 @safe unittest
6124 static assert(is(StringTypeOf!(char[4]) == char[]));
6126 struct S
6128 string s;
6129 alias s this;
6132 struct T
6134 S s;
6135 alias s this;
6138 static assert(is(StringTypeOf!S == string));
6139 static assert(is(StringTypeOf!T == string));
6144 template AssocArrayTypeOf(T)
6146 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6147 alias X = AssocArrayTypeOf!AT;
6148 else
6149 alias X = OriginalType!T;
6151 static if (__traits(isAssociativeArray, X))
6153 alias AssocArrayTypeOf = X;
6155 else
6156 static assert(0, T.stringof~" is not an associative array type");
6159 @safe unittest
6161 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6162 static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6163 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6164 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6166 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) ));
6169 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6170 static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6171 static foreach (P; AliasSeq!TypeQualifierList)
6172 static foreach (Q; AliasSeq!TypeQualifierList)
6173 static foreach (R; AliasSeq!TypeQualifierList)
6175 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6181 template BuiltinTypeOf(T)
6183 static if (is(T : void))
6184 alias BuiltinTypeOf = void;
6185 else
6187 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6188 alias X = BuiltinTypeOf!AT;
6189 else
6190 alias X = OriginalType!T;
6191 static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6192 __traits(isStaticArray, X) || is(X == E[], E) ||
6193 __traits(isAssociativeArray, X) || is(X == typeof(null)))
6194 alias BuiltinTypeOf = X;
6195 else
6196 static assert(0);
6200 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6201 // isSomething
6202 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6205 * Detect whether `T` is a built-in boolean type or enum of boolean base type.
6207 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6210 @safe unittest
6212 static assert( isBoolean!bool);
6213 enum EB : bool { a = true }
6214 static assert( isBoolean!EB);
6216 struct SubTypeOfBool
6218 bool val;
6219 alias val this;
6221 static assert(!isBoolean!(SubTypeOfBool));
6224 @safe unittest
6226 static struct S(T)
6228 T t;
6229 alias t this;
6231 static assert(!isIntegral!(S!bool));
6235 * Detect whether `T` is a built-in integral type.
6236 * Integral types are `byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`,
6237 * and enums with an integral type as its base type.
6238 * Params:
6239 * T = type to test
6240 * Returns:
6241 * `true` if `T` is an integral type
6242 * Note:
6243 * this is not the same as $(LINK2 https://dlang.org/spec/traits.html#isIntegral, `__traits(isIntegral)`)
6245 template isIntegral(T)
6247 static if (!__traits(isIntegral, T))
6248 enum isIntegral = false;
6249 else static if (is(T U == enum))
6250 enum isIntegral = isIntegral!U;
6251 else
6252 enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6253 && !is(immutable T == immutable bool) && !is(T == __vector);
6257 @safe unittest
6259 static assert(
6260 isIntegral!byte &&
6261 isIntegral!short &&
6262 isIntegral!int &&
6263 isIntegral!long &&
6264 isIntegral!(const(long)) &&
6265 isIntegral!(immutable(long))
6268 static assert(
6269 !isIntegral!bool &&
6270 !isIntegral!char &&
6271 !isIntegral!double
6274 // types which act as integral values do not pass
6275 struct S
6277 int val;
6278 alias val this;
6281 static assert(!isIntegral!S);
6284 @safe unittest
6286 static foreach (T; IntegralTypeList)
6288 static foreach (Q; TypeQualifierList)
6290 static assert( isIntegral!(Q!T));
6291 static assert(!isIntegral!(SubTypeOf!(Q!T)));
6295 static assert(!isIntegral!float);
6297 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
6298 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6299 enum EI : int { a = -1, b = 0, c = 1 }
6300 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU);
6301 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI);
6305 * Detect whether `T` is a built-in floating point type.
6307 * See also: $(DDSUBLINK spec/traits, isFloating, `__traits(isFloating, T)`)
6309 // is(T : real) to discount complex types
6310 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6313 @safe unittest
6315 static assert(
6316 isFloatingPoint!float &&
6317 isFloatingPoint!double &&
6318 isFloatingPoint!real &&
6319 isFloatingPoint!(const(real)) &&
6320 isFloatingPoint!(immutable(real))
6323 static assert(!isFloatingPoint!int);
6325 // types which act as floating point values do not pass
6326 struct S
6328 float val;
6329 alias val this;
6332 static assert(!isFloatingPoint!S);
6335 @safe unittest
6337 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6339 static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6341 static foreach (Q; TypeQualifierList)
6343 static assert( isFloatingPoint!(Q!T));
6344 static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6347 static foreach (T; IntegralTypeList)
6349 static foreach (Q; TypeQualifierList)
6351 static assert(!isFloatingPoint!(Q!T));
6354 static if (is(__vector(float[4])))
6356 static assert(!isFloatingPoint!(__vector(float[4])));
6361 * Detect whether `T` is a built-in numeric type (integral or floating
6362 * point).
6364 template isNumeric(T)
6366 static if (!__traits(isArithmetic, T))
6367 enum isNumeric = false;
6368 else static if (__traits(isFloating, T))
6369 enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6370 else static if (is(T U == enum))
6371 enum isNumeric = isNumeric!U;
6372 else
6373 enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6374 && !is(immutable T == immutable bool) && !is(T == __vector);
6378 @safe unittest
6380 static assert(
6381 isNumeric!byte &&
6382 isNumeric!short &&
6383 isNumeric!int &&
6384 isNumeric!long &&
6385 isNumeric!float &&
6386 isNumeric!double &&
6387 isNumeric!real &&
6388 isNumeric!(const(real)) &&
6389 isNumeric!(immutable(real))
6392 static assert(
6393 !isNumeric!void &&
6394 !isNumeric!bool &&
6395 !isNumeric!char &&
6396 !isNumeric!wchar &&
6397 !isNumeric!dchar
6400 // types which act as numeric values do not pass
6401 struct S
6403 int val;
6404 alias val this;
6407 static assert(!isNumeric!S);
6410 @safe unittest
6412 static foreach (T; AliasSeq!(NumericTypeList))
6414 static foreach (Q; TypeQualifierList)
6416 static assert( isNumeric!(Q!T));
6417 static assert(!isNumeric!(SubTypeOf!(Q!T)));
6421 static struct S(T)
6423 T t;
6424 alias t this;
6426 static assert(!isNumeric!(S!int));
6428 enum EChar : char { a = 0, }
6429 static assert(!isNumeric!EChar);
6431 static if (is(__vector(float[4])))
6433 static assert(!isNumeric!(__vector(float[4])));
6435 static if (is(__vector(int[4])))
6437 static assert(!isNumeric!(__vector(int[4])));
6440 static assert(!isNumeric!ifloat);
6441 static assert(!isNumeric!cfloat);
6445 * Detect whether `T` is a scalar type (a built-in numeric, character or
6446 * boolean type).
6448 * See also: $(DDSUBLINK spec/traits, isScalar, `__traits(isScalar, T)`)
6450 // is(T : real) to discount complex types
6451 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6454 @safe unittest
6456 static assert(!isScalarType!void);
6457 static assert( isScalarType!(immutable(byte)));
6458 static assert( isScalarType!(immutable(ushort)));
6459 static assert( isScalarType!(immutable(int)));
6460 static assert( isScalarType!(ulong));
6461 static assert( isScalarType!(shared(float)));
6462 static assert( isScalarType!(shared(const bool)));
6463 static assert( isScalarType!(const(char)));
6464 static assert( isScalarType!(wchar));
6465 static assert( isScalarType!(const(dchar)));
6466 static assert( isScalarType!(const(double)));
6467 static assert( isScalarType!(const(real)));
6470 @safe unittest
6472 static struct S(T)
6474 T t;
6475 alias t this;
6477 static assert(!isScalarType!(S!int));
6481 * Detect whether `T` is a basic type (scalar type or void).
6483 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6486 @safe unittest
6488 static assert(isBasicType!void);
6489 static assert(isBasicType!(const(void)));
6490 static assert(isBasicType!(shared(void)));
6491 static assert(isBasicType!(immutable(void)));
6492 static assert(isBasicType!(shared const(void)));
6493 static assert(isBasicType!(shared inout(void)));
6494 static assert(isBasicType!(shared inout const(void)));
6495 static assert(isBasicType!(inout(void)));
6496 static assert(isBasicType!(inout const(void)));
6497 static assert(isBasicType!(immutable(int)));
6498 static assert(isBasicType!(shared(float)));
6499 static assert(isBasicType!(shared(const bool)));
6500 static assert(isBasicType!(const(dchar)));
6504 * Detect whether `T` is a built-in unsigned numeric type.
6506 template isUnsigned(T)
6508 static if (!__traits(isUnsigned, T))
6509 enum isUnsigned = false;
6510 else static if (is(T U == enum))
6511 enum isUnsigned = isUnsigned!U;
6512 else
6513 enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6514 && !is(immutable T == immutable bool) && !is(T == __vector);
6518 @safe unittest
6520 static assert(
6521 isUnsigned!uint &&
6522 isUnsigned!ulong
6525 static assert(
6526 !isUnsigned!char &&
6527 !isUnsigned!int &&
6528 !isUnsigned!long &&
6529 !isUnsigned!char &&
6530 !isUnsigned!wchar &&
6531 !isUnsigned!dchar
6535 @safe unittest
6537 static foreach (T; AliasSeq!(UnsignedIntTypeList))
6539 static foreach (Q; TypeQualifierList)
6541 static assert( isUnsigned!(Q!T));
6542 static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6546 static struct S(T)
6548 T t;
6549 alias t this;
6551 static assert(!isUnsigned!(S!uint));
6553 enum EChar : char { a = 0, }
6554 static assert(!isUnsigned!EChar);
6556 static if (is(__vector(uint[4])))
6558 static assert(!isUnsigned!(__vector(uint[4])));
6563 * Detect whether `T` is a built-in signed numeric type.
6565 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6566 && is(T : real);
6569 @safe unittest
6571 static assert(
6572 isSigned!int &&
6573 isSigned!long
6576 static assert(
6577 !isSigned!uint &&
6578 !isSigned!ulong
6582 @safe unittest
6584 enum E { e1 = 0 }
6585 static assert(isSigned!E);
6587 enum Eubyte : ubyte { e1 = 0 }
6588 static assert(!isSigned!Eubyte);
6590 static foreach (T; AliasSeq!(SignedIntTypeList))
6592 static foreach (Q; TypeQualifierList)
6594 static assert( isSigned!(Q!T));
6595 static assert(!isSigned!(SubTypeOf!(Q!T)));
6599 static struct S(T)
6601 T t;
6602 alias t this;
6604 static assert(!isSigned!(S!uint));
6606 static if (is(__vector(int[4])))
6608 static assert(!isSigned!(__vector(int[4])));
6611 static assert(!isSigned!ifloat);
6612 static assert(!isSigned!cfloat);
6615 // https://issues.dlang.org/show_bug.cgi?id=17196
6616 @safe unittest
6618 static assert(isUnsigned!bool == false);
6619 static assert(isSigned!bool == false);
6623 * Detect whether `T` is one of the built-in character types.
6625 * The built-in char types are any of `char`, `wchar` or `dchar`, with
6626 * or without qualifiers.
6628 template isSomeChar(T)
6630 static if (!__traits(isUnsigned, T))
6631 enum isSomeChar = false;
6632 else static if (is(T U == enum))
6633 enum isSomeChar = isSomeChar!U;
6634 else
6635 enum isSomeChar = !__traits(isZeroInit, T);
6639 @safe unittest
6641 //Char types
6642 static assert( isSomeChar!char);
6643 static assert( isSomeChar!wchar);
6644 static assert( isSomeChar!dchar);
6645 static assert( isSomeChar!(typeof('c')));
6646 static assert( isSomeChar!(immutable char));
6647 static assert( isSomeChar!(const dchar));
6649 //Non char types
6650 static assert(!isSomeChar!int);
6651 static assert(!isSomeChar!byte);
6652 static assert(!isSomeChar!string);
6653 static assert(!isSomeChar!wstring);
6654 static assert(!isSomeChar!dstring);
6655 static assert(!isSomeChar!(char[4]));
6658 @safe unittest
6660 enum EC : char { a = 'x', b = 'y' }
6662 static foreach (T; AliasSeq!(CharTypeList, EC))
6664 static foreach (Q; TypeQualifierList)
6666 static assert( isSomeChar!( Q!T ));
6667 static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6671 // alias-this types are not allowed
6672 static struct S(T)
6674 T t;
6675 alias t this;
6677 static assert(!isSomeChar!(S!char));
6681 Detect whether `T` is one of the built-in string types.
6683 The built-in string types are `Char[]`, where `Char` is any of `char`,
6684 `wchar` or `dchar`, with or without qualifiers.
6686 Static arrays of characters (like `char[80]`) are not considered
6687 built-in string types.
6689 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6692 @safe unittest
6694 //String types
6695 static assert( isSomeString!string);
6696 static assert( isSomeString!(wchar[]));
6697 static assert( isSomeString!(dchar[]));
6698 static assert( isSomeString!(typeof("aaa")));
6699 static assert( isSomeString!(const(char)[]));
6701 //Non string types
6702 static assert(!isSomeString!int);
6703 static assert(!isSomeString!(int[]));
6704 static assert(!isSomeString!(byte[]));
6705 static assert(!isSomeString!(typeof(null)));
6706 static assert(!isSomeString!(char[4]));
6708 enum ES : string { a = "aaa", b = "bbb" }
6709 static assert(!isSomeString!ES);
6711 static struct Stringish
6713 string str;
6714 alias str this;
6716 static assert(!isSomeString!Stringish);
6719 @safe unittest
6721 static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6723 static assert( isSomeString!( T ));
6724 static assert(!isSomeString!(SubTypeOf!(T)));
6726 enum C : char { _ = 0 }
6727 static assert(!isSomeString!(C[]));
6731 * Detect whether type `T` is a narrow string.
6733 * All arrays that use char, wchar, and their qualified versions are narrow
6734 * strings. (Those include string and wstring).
6736 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6739 @safe unittest
6741 static assert(isNarrowString!string);
6742 static assert(isNarrowString!wstring);
6743 static assert(isNarrowString!(char[]));
6744 static assert(isNarrowString!(wchar[]));
6746 static assert(!isNarrowString!dstring);
6747 static assert(!isNarrowString!(dchar[]));
6749 static assert(!isNarrowString!(typeof(null)));
6750 static assert(!isNarrowString!(char[4]));
6752 enum ES : string { a = "aaa", b = "bbb" }
6753 static assert(!isNarrowString!ES);
6755 static struct Stringish
6757 string str;
6758 alias str this;
6760 static assert(!isNarrowString!Stringish);
6763 @safe unittest
6765 import std.meta : Alias;
6766 static foreach (T; AliasSeq!(char[], string, wstring))
6768 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6770 static assert( isNarrowString!( Q!T ));
6771 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6775 static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6777 static foreach (Q; TypeQualifierList)
6779 static assert(!isNarrowString!( Q!T ));
6780 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6783 enum C : char { _ = 0 }
6784 static assert(!isNarrowString!(C[]));
6788 * Detects whether `T` is a comparable type. Basic types and structs and
6789 * classes that implement opCmp are ordering comparable.
6791 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6794 @safe unittest
6796 static assert(isOrderingComparable!int);
6797 static assert(isOrderingComparable!string);
6799 static struct Foo {}
6800 static assert(!isOrderingComparable!Foo);
6802 static struct Bar
6804 int a;
6805 auto opCmp(Bar b1) const { return a - b1.a; }
6808 Bar b1 = Bar(5);
6809 Bar b2 = Bar(7);
6810 assert(isOrderingComparable!Bar && b2 > b1);
6813 /// ditto
6814 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6816 @safe unittest
6818 static assert(isEqualityComparable!int);
6819 static assert(isEqualityComparable!string);
6820 static assert(!isEqualityComparable!void);
6822 struct Foo {}
6823 static assert(isEqualityComparable!Foo);
6825 struct Bar
6827 int a;
6828 auto opEquals(Bar b1) const { return a == b1.a; }
6831 Bar b1 = Bar(5);
6832 Bar b2 = Bar(5);
6833 Bar b3 = Bar(7);
6834 static assert(isEqualityComparable!Bar);
6835 assert(b1 == b2);
6836 assert(b1 != b3);
6840 $(RED Warning: This trait will be deprecated as soon as it is no longer used
6841 in Phobos. For a function parameter to safely accept a type
6842 that implicitly converts to string as a string, the conversion
6843 needs to happen at the callsite; otherwise, the conversion is
6844 done inside the function, and in many cases, that means that
6845 local memory is sliced (e.g. if a static array is passed to
6846 the function, then it's copied, and the resulting dynamic
6847 array will be a slice of a local variable). So, if the
6848 resulting string escapes the function, the string refers to
6849 invalid memory, and accessing it would mean accessing invalid
6850 memory. As such, the only safe way for a function to accept
6851 types that implicitly convert to string is for the implicit
6852 conversion to be done at the callsite, and that can only occur
6853 if the parameter is explicitly typed as an array, whereas
6854 using isConvertibleToString in a template constraint would
6855 result in the conversion being done inside the function. As
6856 such, isConvertibleToString is inherently unsafe and is going
6857 to be deprecated.)
6859 Detect whether `T` is a struct, static array, or enum that is implicitly
6860 convertible to a string.
6862 template isConvertibleToString(T)
6864 enum isConvertibleToString =
6865 (isAggregateType!T || isStaticArray!T || is(T == enum))
6866 && is(StringTypeOf!T);
6870 @safe unittest
6872 static struct AliasedString
6874 string s;
6875 alias s this;
6878 enum StringEnum { a = "foo" }
6880 assert(!isConvertibleToString!string);
6881 assert(isConvertibleToString!AliasedString);
6882 assert(isConvertibleToString!StringEnum);
6883 assert(isConvertibleToString!(char[25]));
6884 assert(!isConvertibleToString!(char[]));
6887 // https://issues.dlang.org/show_bug.cgi?id=16573
6888 @safe unittest
6890 enum I : int { foo = 1 }
6891 enum S : string { foo = "foo" }
6892 assert(!isConvertibleToString!I);
6893 assert(isConvertibleToString!S);
6896 package template convertToString(T)
6898 static if (isConvertibleToString!T)
6899 alias convertToString = StringTypeOf!T;
6900 else
6901 alias convertToString = T;
6905 * Detect whether type `T` is a string that will be autodecoded.
6907 * Given a type `S` that is one of:
6908 * $(OL
6909 * $(LI `const(char)[]`)
6910 * $(LI `const(wchar)[]`)
6912 * Type `T` can be one of:
6913 * $(OL
6914 * $(LI `S`)
6915 * $(LI implicitly convertible to `T`)
6916 * $(LI an enum with a base type `T`)
6917 * $(LI an aggregate with a base type `T`)
6919 * with the proviso that `T` cannot be a static array.
6921 * Params:
6922 * T = type to be tested
6924 * Returns:
6925 * true if T represents a string that is subject to autodecoding
6927 * See Also:
6928 * $(LREF isNarrowString)
6930 template isAutodecodableString(T)
6932 import std.range.primitives : autodecodeStrings;
6934 enum isAutodecodableString = autodecodeStrings &&
6935 (is(T : const char[]) || is(T : const wchar[]))
6936 && !is(T : U[n], U, size_t n)
6937 && !is(immutable T : immutable noreturn[]);
6941 @safe unittest
6943 static struct Stringish
6945 string s;
6946 alias s this;
6948 static assert(isAutodecodableString!wstring);
6949 static assert(isAutodecodableString!Stringish);
6950 static assert(!isAutodecodableString!dstring);
6952 enum E : const(char)[3] { X = "abc" }
6953 enum F : const(char)[] { X = "abc" }
6954 enum G : F { X = F.init }
6956 static assert(isAutodecodableString!(char[]));
6957 static assert(!isAutodecodableString!(E));
6958 static assert(isAutodecodableString!(F));
6959 static assert(isAutodecodableString!(G));
6961 struct Stringish2
6963 Stringish s;
6964 alias s this;
6967 enum H : Stringish { X = Stringish() }
6968 enum I : Stringish2 { X = Stringish2() }
6970 static assert(isAutodecodableString!(H));
6971 static assert(isAutodecodableString!(I));
6973 static assert(!isAutodecodableString!(noreturn[]));
6974 static assert(!isAutodecodableString!(immutable(noreturn)[]));
6978 * Detect whether type `T` is a static array.
6980 * See also: $(DDSUBLINK spec/traits, isStaticArray, `__traits(isStaticArray, T)`)
6982 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6985 @safe unittest
6987 static assert( isStaticArray!(int[3]));
6988 static assert( isStaticArray!(const(int)[5]));
6989 static assert( isStaticArray!(const(int)[][5]));
6991 static assert(!isStaticArray!(const(int)[]));
6992 static assert(!isStaticArray!(immutable(int)[]));
6993 static assert(!isStaticArray!(const(int)[4][]));
6994 static assert(!isStaticArray!(int[]));
6995 static assert(!isStaticArray!(int[char]));
6996 static assert(!isStaticArray!(int[1][]));
6997 static assert(!isStaticArray!(int[int]));
6998 static assert(!isStaticArray!int);
7001 @safe unittest
7003 static foreach (T; AliasSeq!(int[51], int[][2],
7004 char[][int][11], immutable char[13u],
7005 const(real)[1], const(real)[1][1], void[0]))
7007 static foreach (Q; TypeQualifierList)
7009 static assert( isStaticArray!( Q!T ));
7010 static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
7014 //enum ESA : int[1] { a = [1], b = [2] }
7015 //static assert( isStaticArray!ESA);
7019 * Detect whether type `T` is a dynamic array.
7021 template isDynamicArray(T)
7023 static if (is(T == U[], U))
7024 enum bool isDynamicArray = true;
7025 else static if (is(T U == enum))
7026 // BUG: isDynamicArray / isStaticArray considers enums
7027 // with appropriate base types as dynamic/static arrays
7028 // Retain old behaviour for now, see
7029 // https://github.com/dlang/phobos/pull/7574
7030 enum bool isDynamicArray = isDynamicArray!U;
7031 else
7032 enum bool isDynamicArray = false;
7036 @safe unittest
7038 static assert( isDynamicArray!(int[]));
7039 static assert( isDynamicArray!(string));
7040 static assert( isDynamicArray!(long[3][]));
7042 static assert(!isDynamicArray!(int[5]));
7043 static assert(!isDynamicArray!(typeof(null)));
7046 @safe unittest
7048 import std.meta : AliasSeq;
7049 static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
7051 static foreach (Q; TypeQualifierList)
7053 static assert( isDynamicArray!( Q!T ));
7054 static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
7058 static assert(!isDynamicArray!(int[5]));
7060 static struct AliasThis
7062 int[] values;
7063 alias values this;
7066 static assert(!isDynamicArray!AliasThis);
7068 // https://github.com/dlang/phobos/pull/7574/files#r464115492
7069 enum E : string
7071 a = "a",
7072 b = "b",
7074 static assert( isDynamicArray!E);
7078 * Detect whether type `T` is an array (static or dynamic; for associative
7079 * arrays see $(LREF isAssociativeArray)).
7081 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
7084 @safe unittest
7086 static assert( isArray!(int[]));
7087 static assert( isArray!(int[5]));
7088 static assert( isArray!(string));
7090 static assert(!isArray!uint);
7091 static assert(!isArray!(uint[uint]));
7092 static assert(!isArray!(typeof(null)));
7095 @safe unittest
7097 import std.meta : AliasSeq;
7098 static foreach (T; AliasSeq!(int[], int[5], void[]))
7100 static foreach (Q; TypeQualifierList)
7102 static assert( isArray!(Q!T));
7103 static assert(!isArray!(SubTypeOf!(Q!T)));
7109 * Detect whether `T` is an associative array type
7111 * See also: $(DDSUBLINK spec/traits, isAssociativeArray, `__traits(isAssociativeArray, T)`)
7113 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
7116 @safe unittest
7118 struct S;
7120 static assert( isAssociativeArray!(int[string]));
7121 static assert( isAssociativeArray!(S[S]));
7122 static assert(!isAssociativeArray!(string[]));
7123 static assert(!isAssociativeArray!S);
7124 static assert(!isAssociativeArray!(int[4]));
7127 @safe unittest
7129 struct Foo
7131 @property uint[] keys() { return null; }
7132 @property uint[] values() { return null; }
7135 static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7137 static foreach (Q; TypeQualifierList)
7139 static assert( isAssociativeArray!(Q!T));
7140 static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7144 static assert(!isAssociativeArray!Foo);
7145 static assert(!isAssociativeArray!int);
7146 static assert(!isAssociativeArray!(int[]));
7147 static assert(!isAssociativeArray!(typeof(null)));
7149 //enum EAA : int[int] { a = [1:1], b = [2:2] }
7150 //static assert( isAssociativeArray!EAA);
7154 * Detect whether type `T` is a builtin type.
7156 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7159 @safe unittest
7161 class C;
7162 union U;
7163 struct S;
7164 interface I;
7166 static assert( isBuiltinType!void);
7167 static assert( isBuiltinType!string);
7168 static assert( isBuiltinType!(int[]));
7169 static assert( isBuiltinType!(C[string]));
7170 static assert( isBuiltinType!(typeof(null)));
7171 static assert(!isBuiltinType!C);
7172 static assert(!isBuiltinType!U);
7173 static assert(!isBuiltinType!S);
7174 static assert(!isBuiltinType!I);
7175 static assert(!isBuiltinType!(void delegate(int)));
7179 * Detect whether type `T` is a SIMD vector type.
7181 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7184 @safe unittest
7186 static if (is(__vector(float[4])))
7188 alias SimdVec = __vector(float[4]);
7189 static assert(isSIMDVector!(__vector(float[4])));
7190 static assert(isSIMDVector!SimdVec);
7192 static assert(!isSIMDVector!uint);
7193 static assert(!isSIMDVector!(float[4]));
7197 * Detect whether type `T` is a pointer.
7199 enum bool isPointer(T) = is(T == U*, U);
7202 @safe unittest
7204 void fun();
7206 static assert( isPointer!(int*));
7207 static assert( isPointer!(int function()));
7208 static assert(!isPointer!int);
7209 static assert(!isPointer!string);
7210 static assert(!isPointer!(typeof(null)));
7211 static assert(!isPointer!(typeof(fun)));
7212 static assert(!isPointer!(int delegate()));
7215 @safe unittest
7217 static foreach (T; AliasSeq!(int*, void*, char[]*))
7219 static foreach (Q; TypeQualifierList)
7221 static assert( isPointer!(Q!T));
7222 static assert(!isPointer!(SubTypeOf!(Q!T)));
7226 static assert(!isPointer!uint);
7227 static assert(!isPointer!(uint[uint]));
7228 static assert(!isPointer!(char[]));
7229 static assert(!isPointer!(typeof(null)));
7233 Returns the target type of a pointer.
7235 alias PointerTarget(T : T*) = T;
7238 @safe unittest
7240 static assert(is(PointerTarget!(int*) == int));
7241 static assert(is(PointerTarget!(void*) == void));
7245 * Detect whether type `T` is an aggregate type.
7247 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
7248 is(T == class) || is(T == interface);
7251 @safe unittest
7253 class C;
7254 union U;
7255 struct S;
7256 interface I;
7258 static assert( isAggregateType!C);
7259 static assert( isAggregateType!U);
7260 static assert( isAggregateType!S);
7261 static assert( isAggregateType!I);
7262 static assert(!isAggregateType!void);
7263 static assert(!isAggregateType!string);
7264 static assert(!isAggregateType!(int[]));
7265 static assert(!isAggregateType!(C[string]));
7266 static assert(!isAggregateType!(void delegate(int)));
7270 * Returns `true` if T can be iterated over using a `foreach` loop with
7271 * a single loop variable of automatically inferred type, regardless of how
7272 * the `foreach` loop is implemented. This includes ranges, structs/classes
7273 * that define `opApply` with a single loop variable, and builtin dynamic,
7274 * static and associative arrays.
7276 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7279 @safe unittest
7281 struct OpApply
7283 int opApply(scope int delegate(ref uint) dg) { assert(0); }
7286 struct Range
7288 @property uint front() { assert(0); }
7289 void popFront() { assert(0); }
7290 enum bool empty = false;
7293 static assert( isIterable!(uint[]));
7294 static assert( isIterable!OpApply);
7295 static assert( isIterable!(uint[string]));
7296 static assert( isIterable!Range);
7298 static assert(!isIterable!uint);
7302 * Returns true if T is not const or immutable. Note that isMutable is true for
7303 * string, or immutable(char)[], because the 'head' is mutable.
7305 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7308 @safe unittest
7310 static assert( isMutable!int);
7311 static assert( isMutable!string);
7312 static assert( isMutable!(shared int));
7313 static assert( isMutable!(shared const(int)[]));
7315 static assert(!isMutable!(const int));
7316 static assert(!isMutable!(inout int));
7317 static assert(!isMutable!(shared(const int)));
7318 static assert(!isMutable!(shared(inout int)));
7319 static assert(!isMutable!(immutable string));
7323 * Returns true if T is an instance of the template S.
7325 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7326 /// ditto
7327 template isInstanceOf(alias S, alias T)
7329 enum impl(alias T : S!Args, Args...) = true;
7330 enum impl(alias T) = false;
7331 enum isInstanceOf = impl!T;
7335 @safe unittest
7337 static struct Foo(T...) { }
7338 static struct Bar(T...) { }
7339 static struct Doo(T) { }
7340 static struct ABC(int x) { }
7341 static void fun(T)() { }
7342 template templ(T) { }
7344 static assert(isInstanceOf!(Foo, Foo!int));
7345 static assert(!isInstanceOf!(Foo, Bar!int));
7346 static assert(!isInstanceOf!(Foo, int));
7347 static assert(isInstanceOf!(Doo, Doo!int));
7348 static assert(isInstanceOf!(ABC, ABC!1));
7349 static assert(!isInstanceOf!(Foo, Foo));
7350 static assert(isInstanceOf!(fun, fun!int));
7351 static assert(isInstanceOf!(templ, templ!int));
7355 * To use `isInstanceOf` to check the identity of a template while inside of said
7356 * template, use $(LREF TemplateOf).
7358 @safe unittest
7360 static struct A(T = void)
7362 // doesn't work as expected, only accepts A when T = void
7363 void func(B)(B b) if (isInstanceOf!(A, B)) {}
7365 // correct behavior
7366 void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {}
7369 A!(void) a1;
7370 A!(void) a2;
7371 A!(int) a3;
7373 static assert(!__traits(compiles, a1.func(a3)));
7374 static assert( __traits(compiles, a1.method(a2)));
7375 static assert( __traits(compiles, a1.method(a3)));
7378 @safe unittest
7380 static void fun1(T)() { }
7381 static void fun2(T)() { }
7382 template templ1(T) { }
7383 template templ2(T) { }
7385 static assert(!isInstanceOf!(fun1, fun2!int));
7386 static assert(!isInstanceOf!(templ1, templ2!int));
7390 * Check whether the tuple T is an expression tuple.
7391 * An expression tuple only contains expressions.
7393 * See_Also: $(LREF isTypeTuple).
7395 template isExpressions(T...)
7397 static foreach (Ti; T)
7399 static if (!is(typeof(isExpressions) == bool) && // not yet defined
7400 (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7402 enum isExpressions = false;
7405 static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7407 enum isExpressions = true;
7412 @safe unittest
7414 static assert(isExpressions!(1, 2.0, "a"));
7415 static assert(!isExpressions!(int, double, string));
7416 static assert(!isExpressions!(int, 2.0, "a"));
7420 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7423 alias isExpressionTuple = isExpressions;
7425 @safe unittest
7427 void foo();
7428 static int bar() { return 42; }
7429 immutable aa = [ 1: -1 ];
7430 alias myint = int;
7432 static assert( isExpressionTuple!(42));
7433 static assert( isExpressionTuple!aa);
7434 static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7435 static assert( isExpressionTuple!(bar()));
7437 static assert(!isExpressionTuple!isExpressionTuple);
7438 static assert(!isExpressionTuple!foo);
7439 static assert(!isExpressionTuple!( (a) { } ));
7440 static assert(!isExpressionTuple!int);
7441 static assert(!isExpressionTuple!myint);
7446 * Check whether the tuple `T` is a type tuple.
7447 * A type tuple only contains types.
7449 * See_Also: $(LREF isExpressions).
7451 enum isTypeTuple(T...) =
7453 static foreach (U; T)
7454 static if (!is(U))
7455 if (__ctfe)
7456 return false;
7457 return true;
7458 }();
7461 @safe unittest
7463 static assert(isTypeTuple!(int, float, string));
7464 static assert(!isTypeTuple!(1, 2.0, "a"));
7465 static assert(!isTypeTuple!(1, double, string));
7468 @safe unittest
7470 class C {}
7471 void func(int) {}
7472 auto c = new C;
7473 enum CONST = 42;
7475 static assert( isTypeTuple!int);
7476 static assert( isTypeTuple!string);
7477 static assert( isTypeTuple!C);
7478 static assert( isTypeTuple!(typeof(func)));
7479 static assert( isTypeTuple!(int, char, double));
7481 static assert(!isTypeTuple!c);
7482 static assert(!isTypeTuple!isTypeTuple);
7483 static assert(!isTypeTuple!CONST);
7488 Detect whether symbol or type `T` is a function pointer.
7490 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7493 @safe unittest
7495 static void foo() {}
7496 void bar() {}
7498 auto fpfoo = &foo;
7499 static assert( isFunctionPointer!fpfoo);
7500 static assert( isFunctionPointer!(void function()));
7502 auto dgbar = &bar;
7503 static assert(!isFunctionPointer!dgbar);
7504 static assert(!isFunctionPointer!(void delegate()));
7505 static assert(!isFunctionPointer!foo);
7506 static assert(!isFunctionPointer!bar);
7508 static assert( isFunctionPointer!((int a) {}));
7512 Detect whether symbol or type `T` is a delegate.
7514 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7517 @safe unittest
7519 static void sfunc() { }
7520 int x;
7521 void func() { x++; }
7523 int delegate() dg;
7524 assert(isDelegate!dg);
7525 assert(isDelegate!(int delegate()));
7526 assert(isDelegate!(typeof(&func)));
7528 int function() fp;
7529 assert(!isDelegate!fp);
7530 assert(!isDelegate!(int function()));
7531 assert(!isDelegate!(typeof(&sfunc)));
7535 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7537 Params:
7538 T = The type to check
7539 Returns:
7540 A `bool`
7542 enum bool isSomeFunction(alias T) =
7543 is(T == return) ||
7544 is(typeof(T) == return) ||
7545 is(typeof(&T) == return); // @property
7548 @safe unittest
7550 static real func(ref int) { return 0; }
7551 static void prop() @property { }
7552 class C
7554 real method(ref int) { return 0; }
7555 real prop() @property { return 0; }
7557 auto c = new C;
7558 auto fp = &func;
7559 auto dg = &c.method;
7561 static assert( isSomeFunction!func);
7562 static assert( isSomeFunction!prop);
7563 static assert( isSomeFunction!(C.method));
7564 static assert( isSomeFunction!(C.prop));
7565 static assert( isSomeFunction!(c.prop));
7566 static assert( isSomeFunction!fp);
7567 static assert( isSomeFunction!dg);
7569 real val;
7570 static assert(!isSomeFunction!int);
7571 static assert(!isSomeFunction!val);
7574 @safe unittest
7576 void nestedFunc() { }
7577 void nestedProp() @property { }
7578 static assert(isSomeFunction!nestedFunc);
7579 static assert(isSomeFunction!nestedProp);
7580 static assert(isSomeFunction!(real function(ref int)));
7581 static assert(isSomeFunction!(real delegate(ref int)));
7582 static assert(isSomeFunction!((int a) { return a; }));
7583 static assert(!isSomeFunction!isSomeFunction);
7587 Detect whether `T` is a callable object, which can be called with the
7588 function call operator `$(LPAREN)...$(RPAREN)`.
7590 template isCallable(alias callable)
7592 static if (is(typeof(&callable.opCall) == delegate))
7593 // T is a object which has a member function opCall().
7594 enum bool isCallable = true;
7595 else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7596 // T is a type which has a static member function opCall().
7597 enum bool isCallable = true;
7598 else static if (is(typeof(&callable.opCall!()) TemplateInstanceType))
7600 enum bool isCallable = isCallable!TemplateInstanceType;
7602 else static if (is(typeof(&callable!()) TemplateInstanceType))
7604 enum bool isCallable = isCallable!TemplateInstanceType;
7606 else
7608 enum bool isCallable = isSomeFunction!callable;
7612 /// Functions, lambdas, and aggregate types with (static) opCall.
7613 @safe unittest
7615 void f() { }
7616 int g(int x) { return x; }
7618 static assert( isCallable!f);
7619 static assert( isCallable!g);
7621 class C { int opCall(int) { return 0; } }
7622 auto c = new C;
7623 struct S { static int opCall(int) { return 0; } }
7624 interface I { real value() @property; }
7626 static assert( isCallable!c);
7627 static assert( isCallable!(c.opCall));
7628 static assert( isCallable!S);
7629 static assert( isCallable!(I.value));
7630 static assert( isCallable!((int a) { return a; }));
7632 static assert(!isCallable!I);
7635 /// Templates
7636 @safe unittest
7638 void f()() { }
7639 T g(T = int)(T x) { return x; }
7640 struct S1 { static void opCall()() { } }
7641 struct S2 { static T opCall(T = int)(T x) {return x; } }
7643 static assert( isCallable!f);
7644 static assert( isCallable!g);
7645 static assert( isCallable!S1);
7646 static assert( isCallable!S2);
7649 /// Overloaded functions and function templates.
7650 @safe unittest
7652 static struct Wrapper
7654 void f() { }
7655 int f(int x) { return x; }
7657 void g()() { }
7658 T g(T = int)(T x) { return x; }
7661 static assert(isCallable!(Wrapper.f));
7662 static assert(isCallable!(Wrapper.g));
7667 Detect whether `S` is an abstract function.
7669 See also: $(DDSUBLINK spec/traits, isAbstractFunction, `__traits(isAbstractFunction, S)`)
7670 Params:
7671 S = The symbol to check
7672 Returns:
7673 A `bool`
7675 enum isAbstractFunction(alias S) = __traits(isAbstractFunction, S);
7678 @safe unittest
7680 struct S { void foo() { } }
7681 class C { void foo() { } }
7682 class AC { abstract void foo(); }
7683 static assert(!isAbstractFunction!(int));
7684 static assert(!isAbstractFunction!(S.foo));
7685 static assert(!isAbstractFunction!(C.foo));
7686 static assert( isAbstractFunction!(AC.foo));
7690 * Detect whether `S` is a final function.
7692 * See also: $(DDSUBLINK spec/traits, isFinalFunction, `__traits(isFinalFunction, S)`)
7694 enum isFinalFunction(alias S) = __traits(isFinalFunction, S);
7697 @safe unittest
7699 struct S { void bar() { } }
7700 final class FC { void foo(); }
7701 class C
7703 void bar() { }
7704 final void foo();
7706 static assert(!isFinalFunction!(int));
7707 static assert(!isFinalFunction!(S.bar));
7708 static assert( isFinalFunction!(FC.foo));
7709 static assert(!isFinalFunction!(C.bar));
7710 static assert( isFinalFunction!(C.foo));
7714 Determines if `f` is a function that requires a context pointer.
7716 Params:
7717 f = The type to check
7718 Returns
7719 A `bool`
7721 template isNestedFunction(alias f)
7723 enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7727 @safe unittest
7729 static void f() {}
7730 static void fun()
7732 int i;
7733 int f() { return i; }
7735 static assert(isNestedFunction!(f));
7738 static assert(!isNestedFunction!f);
7741 // https://issues.dlang.org/show_bug.cgi?id=18669
7742 @safe unittest
7744 static class Outer
7746 class Inner
7750 int i;
7751 struct SS
7753 int bar() { return i; }
7755 static assert(!isNestedFunction!(Outer.Inner));
7756 static assert(!isNestedFunction!(SS));
7760 * Detect whether `S` is an abstract class.
7762 * See also: $(DDSUBLINK spec/traits, isAbstractClass, `__traits(isAbstractClass, S)`)
7764 enum isAbstractClass(alias S) = __traits(isAbstractClass, S);
7767 @safe unittest
7769 struct S { }
7770 class C { }
7771 abstract class AC { }
7772 static assert(!isAbstractClass!S);
7773 static assert(!isAbstractClass!C);
7774 static assert( isAbstractClass!AC);
7775 C c;
7776 static assert(!isAbstractClass!c);
7777 AC ac;
7778 static assert( isAbstractClass!ac);
7782 * Detect whether `S` is a final class.
7784 * See also: $(DDSUBLINK spec/traits, isFinalClass, `__traits(isFinalClass, S)`)
7786 enum isFinalClass(alias S) = __traits(isFinalClass, S);
7789 @safe unittest
7791 class C { }
7792 abstract class AC { }
7793 final class FC1 : C { }
7794 final class FC2 { }
7795 static assert(!isFinalClass!C);
7796 static assert(!isFinalClass!AC);
7797 static assert( isFinalClass!FC1);
7798 static assert( isFinalClass!FC2);
7799 C c;
7800 static assert(!isFinalClass!c);
7801 FC1 fc1;
7802 static assert( isFinalClass!fc1);
7805 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7806 // General Types
7807 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7809 version (StdDdoc)
7812 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7814 template Unconst(T)
7816 import core.internal.traits : CoreUnconst = Unconst;
7817 alias Unconst = CoreUnconst!(T);
7820 else
7822 import core.internal.traits : CoreUnconst = Unconst;
7823 alias Unconst = CoreUnconst;
7827 @safe unittest
7829 static assert(is(Unconst!int == int));
7830 static assert(is(Unconst!(const int) == int));
7831 static assert(is(Unconst!(immutable int) == int));
7832 static assert(is(Unconst!(shared int) == shared int));
7833 static assert(is(Unconst!(shared(const int)) == shared int));
7836 @safe unittest
7838 static assert(is(Unconst!( int) == int));
7839 static assert(is(Unconst!( const int) == int));
7840 static assert(is(Unconst!( inout int) == int));
7841 static assert(is(Unconst!( inout const int) == int));
7842 static assert(is(Unconst!(shared int) == shared int));
7843 static assert(is(Unconst!(shared const int) == shared int));
7844 static assert(is(Unconst!(shared inout int) == shared int));
7845 static assert(is(Unconst!(shared inout const int) == shared int));
7846 static assert(is(Unconst!( immutable int) == int));
7848 alias ImmIntArr = immutable(int[]);
7849 static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7853 Removes `shared` qualifier, if any, from type `T`.
7855 Note that while `immutable` is implicitly `shared`, it is unaffected by
7856 Unshared. Only explict `shared` is removed.
7858 template Unshared(T)
7860 static if (is(T == shared U, U))
7861 alias Unshared = U;
7862 else
7863 alias Unshared = T;
7867 @safe unittest
7869 static assert(is(Unshared!int == int));
7870 static assert(is(Unshared!(const int) == const int));
7871 static assert(is(Unshared!(immutable int) == immutable int));
7873 static assert(is(Unshared!(shared int) == int));
7874 static assert(is(Unshared!(shared(const int)) == const int));
7876 static assert(is(Unshared!(shared(int[])) == shared(int)[]));
7879 @safe unittest
7881 static assert(is(Unshared!( int) == int));
7882 static assert(is(Unshared!( const int) == const int));
7883 static assert(is(Unshared!( inout int) == inout int));
7884 static assert(is(Unshared!( inout const int) == inout const int));
7885 static assert(is(Unshared!(shared int) == int));
7886 static assert(is(Unshared!(shared const int) == const int));
7887 static assert(is(Unshared!(shared inout int) == inout int));
7888 static assert(is(Unshared!(shared inout const int) == inout const int));
7889 static assert(is(Unshared!( immutable int) == immutable int));
7892 version (StdDdoc)
7895 Removes all qualifiers, if any, from type `T`.
7897 template Unqual(T)
7899 import core.internal.traits : CoreUnqual = Unqual;
7900 alias Unqual = CoreUnqual!(T);
7903 else
7905 import core.internal.traits : CoreUnqual = Unqual;
7906 alias Unqual = CoreUnqual;
7910 @safe unittest
7912 static assert(is(Unqual!int == int));
7913 static assert(is(Unqual!(const int) == int));
7914 static assert(is(Unqual!(immutable int) == int));
7915 static assert(is(Unqual!(shared int) == int));
7916 static assert(is(Unqual!(shared(const int)) == int));
7919 @safe unittest
7921 static assert(is(Unqual!( int) == int));
7922 static assert(is(Unqual!( const int) == int));
7923 static assert(is(Unqual!( inout int) == int));
7924 static assert(is(Unqual!( inout const int) == int));
7925 static assert(is(Unqual!(shared int) == int));
7926 static assert(is(Unqual!(shared const int) == int));
7927 static assert(is(Unqual!(shared inout int) == int));
7928 static assert(is(Unqual!(shared inout const int) == int));
7929 static assert(is(Unqual!( immutable int) == int));
7931 alias ImmIntArr = immutable(int[]);
7932 static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7935 // [For internal use]
7936 package template ModifyTypePreservingTQ(alias Modifier, T)
7938 import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7939 alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7943 * Copies type qualifiers from `FromType` to `ToType`.
7945 * Supported type qualifiers:
7946 * $(UL
7947 * $(LI `const`)
7948 * $(LI `inout`)
7949 * $(LI `immutable`)
7950 * $(LI `shared`)
7953 template CopyTypeQualifiers(FromType, ToType)
7955 alias T(U) = ToType;
7956 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7960 @safe unittest
7962 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7965 @safe unittest
7967 static assert(is(CopyTypeQualifiers!( real, int) == int));
7968 static assert(is(CopyTypeQualifiers!( const real, int) == const int));
7969 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int));
7970 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int));
7971 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int));
7972 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int));
7973 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int));
7974 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
7975 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int));
7979 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
7980 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
7981 returned type will be the same as `ToType`.
7983 template CopyConstness(FromType, ToType)
7985 alias Unshared(T) = T;
7986 alias Unshared(T: shared U, U) = U;
7988 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
7992 @safe unittest
7994 const(int) i;
7995 CopyConstness!(typeof(i), float) f;
7996 assert( is(typeof(f) == const float));
7998 CopyConstness!(char, uint) u;
7999 assert( is(typeof(u) == uint));
8001 //The 'shared' qualifier will not be copied
8002 assert(!is(CopyConstness!(shared bool, int) == shared int));
8004 //But the constness will be
8005 assert( is(CopyConstness!(shared const real, double) == const double));
8007 //Careful, const(int)[] is a mutable array of const(int)
8008 alias MutT = CopyConstness!(const(int)[], int);
8009 assert(!is(MutT == const(int)));
8011 //Okay, const(int[]) applies to array and contained ints
8012 alias CstT = CopyConstness!(const(int[]), int);
8013 assert( is(CstT == const(int)));
8016 @safe unittest
8018 struct Test
8020 void method1() {}
8021 void method2() const {}
8022 void method3() immutable {}
8025 assert(is(CopyConstness!(typeof(Test.method1), real) == real));
8027 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
8029 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
8032 @safe unittest
8034 assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
8035 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
8038 @safe unittest
8040 static assert(is(CopyConstness!( int, real) == real));
8041 static assert(is(CopyConstness!(const int, real) == const real));
8042 static assert(is(CopyConstness!(inout int, real) == inout real));
8043 static assert(is(CopyConstness!(inout const int, real) == inout const real));
8044 static assert(is(CopyConstness!(shared int, real) == real));
8045 static assert(is(CopyConstness!(shared const int, real) == const real));
8046 static assert(is(CopyConstness!(shared inout int, real) == inout real));
8047 static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
8048 static assert(is(CopyConstness!(immutable int, real) == immutable real));
8052 Returns the inferred type of the loop variable when a variable of type T
8053 is iterated over using a `foreach` loop with a single loop variable and
8054 automatically inferred return type. Note that this may not be the same as
8055 `std.range.ElementType!Range` in the case of narrow strings, or if T
8056 has both opApply and a range interface.
8058 template ForeachType(T)
8060 alias ForeachType = typeof(
8061 (inout int x = 0)
8063 foreach (elem; T.init)
8065 return elem;
8067 assert(0);
8068 }());
8072 @safe unittest
8074 static assert(is(ForeachType!(uint[]) == uint));
8075 static assert(is(ForeachType!string == immutable(char)));
8076 static assert(is(ForeachType!(string[string]) == string));
8077 static assert(is(ForeachType!(inout(int)[]) == inout(int)));
8082 * Strips off all `enum`s from type `T`.
8084 template OriginalType(T)
8086 import core.internal.traits : _OriginalType = OriginalType;
8087 alias OriginalType = _OriginalType!T;
8091 @safe unittest
8093 enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
8094 enum F : E { a = E.a }
8095 alias G = const(F);
8096 static assert(is(OriginalType!E == real));
8097 static assert(is(OriginalType!F == real));
8098 static assert(is(OriginalType!G == const real));
8102 * Get the Key type of an Associative Array.
8104 alias KeyType(V : V[K], K) = K;
8107 @safe unittest
8109 alias Hash = int[string];
8110 static assert(is(KeyType!Hash == string));
8111 static assert(is(ValueType!Hash == int));
8112 KeyType!Hash str = "a"; // str is declared as string
8113 ValueType!Hash num = 1; // num is declared as int
8117 * Get the Value type of an Associative Array.
8119 alias ValueType(V : V[K], K) = V;
8122 @safe unittest
8124 alias Hash = int[string];
8125 static assert(is(KeyType!Hash == string));
8126 static assert(is(ValueType!Hash == int));
8127 KeyType!Hash str = "a"; // str is declared as string
8128 ValueType!Hash num = 1; // num is declared as int
8132 Params:
8133 T = A built in integral or vector type.
8135 Returns:
8136 The corresponding unsigned numeric type for `T` with the
8137 same type qualifiers.
8139 If `T` is not a integral or vector, a compile-time error is given.
8141 template Unsigned(T)
8143 template Impl(T)
8145 static if (is(T : __vector(V[N]), V, size_t N))
8146 alias Impl = __vector(Impl!V[N]);
8147 else static if (isUnsigned!T)
8148 alias Impl = T;
8149 else static if (isSigned!T && !isFloatingPoint!T)
8151 static if (is(T == byte )) alias Impl = ubyte;
8152 static if (is(T == short)) alias Impl = ushort;
8153 static if (is(T == int )) alias Impl = uint;
8154 static if (is(T == long )) alias Impl = ulong;
8155 static if (is(ucent) && is(T == cent )) alias Impl = ucent;
8157 else
8158 static assert(false, "Type " ~ T.stringof ~
8159 " does not have an Unsigned counterpart");
8162 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8166 @safe unittest
8168 static assert(is(Unsigned!(int) == uint));
8169 static assert(is(Unsigned!(long) == ulong));
8170 static assert(is(Unsigned!(const short) == const ushort));
8171 static assert(is(Unsigned!(immutable byte) == immutable ubyte));
8172 static assert(is(Unsigned!(inout int) == inout uint));
8176 /// Unsigned types are forwarded
8177 @safe unittest
8179 static assert(is(Unsigned!(uint) == uint));
8180 static assert(is(Unsigned!(const uint) == const uint));
8182 static assert(is(Unsigned!(ubyte) == ubyte));
8183 static assert(is(Unsigned!(immutable uint) == immutable uint));
8186 @safe unittest
8188 alias U1 = Unsigned!int;
8189 alias U2 = Unsigned!(const(int));
8190 alias U3 = Unsigned!(immutable(int));
8191 static assert(is(U1 == uint));
8192 static assert(is(U2 == const(uint)));
8193 static assert(is(U3 == immutable(uint)));
8194 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8196 alias UV1 = Unsigned!(__vector(int[4]));
8197 alias UV2 = Unsigned!(const(__vector(int[4])));
8198 static assert(is(UV1 == __vector(uint[4])));
8199 static assert(is(UV2 == const(__vector(uint[4]))));
8201 //struct S {}
8202 //alias U2 = Unsigned!S;
8203 //alias U3 = Unsigned!double;
8204 static if (is(ucent))
8206 alias U4 = Unsigned!cent;
8207 alias U5 = Unsigned!(const(cent));
8208 alias U6 = Unsigned!(immutable(cent));
8209 static assert(is(U4 == ucent));
8210 static assert(is(U5 == const(ucent)));
8211 static assert(is(U6 == immutable(ucent)));
8216 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
8217 than one type is of the same size, the leftmost argument of these in will be
8218 returned.
8220 template Largest(T...)
8221 if (T.length >= 1)
8223 alias Largest = T[0];
8224 static foreach (U; T[1 .. $])
8225 Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8229 @safe unittest
8231 static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8232 static assert(is(Largest!(ulong, double) == ulong));
8233 static assert(is(Largest!(double, ulong) == double));
8234 static assert(is(Largest!(uint, byte, double, short) == double));
8235 static if (is(ucent))
8236 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8240 Returns the corresponding signed type for T. T must be a numeric integral type,
8241 otherwise a compile-time error occurs.
8243 template Signed(T)
8245 template Impl(T)
8247 static if (is(T : __vector(V[N]), V, size_t N))
8248 alias Impl = __vector(Impl!V[N]);
8249 else static if (isSigned!T)
8250 alias Impl = T;
8251 else static if (isUnsigned!T)
8253 static if (is(T == ubyte )) alias Impl = byte;
8254 static if (is(T == ushort)) alias Impl = short;
8255 static if (is(T == uint )) alias Impl = int;
8256 static if (is(T == ulong )) alias Impl = long;
8257 static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8259 else
8260 static assert(false, "Type " ~ T.stringof ~
8261 " does not have an Signed counterpart");
8264 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8268 @safe unittest
8270 alias S1 = Signed!uint;
8271 static assert(is(S1 == int));
8272 alias S2 = Signed!(const(uint));
8273 static assert(is(S2 == const(int)));
8274 alias S3 = Signed!(immutable(uint));
8275 static assert(is(S3 == immutable(int)));
8276 static if (is(ucent))
8278 alias S4 = Signed!ucent;
8279 static assert(is(S4 == cent));
8283 @safe unittest
8285 static assert(is(Signed!float == float));
8286 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8288 alias SV1 = Signed!(__vector(uint[4]));
8289 alias SV2 = Signed!(const(__vector(uint[4])));
8290 static assert(is(SV1 == __vector(int[4])));
8291 static assert(is(SV2 == const(__vector(int[4]))));
8297 Returns the most negative value of the numeric type T.
8299 template mostNegative(T)
8300 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8302 static if (is(typeof(T.min_normal)))
8303 enum mostNegative = -T.max;
8304 else static if (T.min == 0)
8305 enum byte mostNegative = 0;
8306 else
8307 enum mostNegative = T.min;
8311 @safe unittest
8313 static assert(mostNegative!float == -float.max);
8314 static assert(mostNegative!double == -double.max);
8315 static assert(mostNegative!real == -real.max);
8316 static assert(mostNegative!bool == false);
8320 @safe unittest
8322 import std.meta : AliasSeq;
8324 static foreach (T; AliasSeq!(bool, byte, short, int, long))
8325 static assert(mostNegative!T == T.min);
8327 static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8328 static assert(mostNegative!T == 0);
8332 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8333 to in multi-term arithmetic expressions.
8335 template Promoted(T)
8336 if (isScalarType!T)
8338 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8342 @safe unittest
8344 ubyte a = 3, b = 5;
8345 static assert(is(typeof(a * b) == Promoted!ubyte));
8346 static assert(is(Promoted!ubyte == int));
8348 static assert(is(Promoted!(shared(bool)) == shared(int)));
8349 static assert(is(Promoted!(const(int)) == const(int)));
8350 static assert(is(Promoted!double == double));
8353 @safe unittest
8355 // promote to int:
8356 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8358 static assert(is(Promoted!T == int));
8359 static assert(is(Promoted!(shared(const T)) == shared(const int)));
8362 // already promoted:
8363 static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8365 static assert(is(Promoted!T == T));
8366 static assert(is(Promoted!(immutable(T)) == immutable(T)));
8370 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8371 // Misc.
8372 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8375 Returns the mangled name of symbol or type `sth`.
8377 `mangledName` is the same as builtin `.mangleof` property, but
8378 might be more convenient in generic code, e.g. as a template argument
8379 when invoking staticMap.
8381 enum mangledName(alias sth) = sth.mangleof;
8384 @safe unittest
8386 import std.meta : AliasSeq;
8387 alias TL = staticMap!(mangledName, int, const int, immutable int);
8388 static assert(TL == AliasSeq!("i", "xi", "yi"));
8391 version (StdUnittest) private void freeFunc(string);
8393 @safe unittest
8395 class C { int value() @property { return 0; } }
8396 static assert(mangledName!int == int.mangleof);
8397 static assert(mangledName!C == C.mangleof);
8398 static assert(mangledName!(C.value) == C.value.mangleof);
8399 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8400 static assert(mangledName!mangledName == "3std6traits11mangledName");
8401 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8402 int x;
8403 // https://issues.dlang.org/show_bug.cgi?id=9148
8404 static if (is(typeof({ return x; }) : int delegate() pure))
8405 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
8406 else
8407 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
8410 @system unittest
8412 // @system due to demangle
8413 // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8414 import std.demangle : demangle;
8415 int foo;
8416 auto foo_demangled = demangle(mangledName!foo);
8417 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8418 foo_demangled);
8420 void bar();
8421 auto bar_demangled = demangle(mangledName!bar);
8422 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8427 // XXX Select & select should go to another module. (functional or algorithm?)
8430 Aliases itself to `T[0]` if the boolean `condition` is `true`
8431 and to `T[1]` otherwise.
8433 template Select(bool condition, T...)
8434 if (T.length == 2)
8436 import std.meta : Alias;
8437 alias Select = Alias!(T[!condition]);
8441 @safe unittest
8443 // can select types
8444 static assert(is(Select!(true, int, long) == int));
8445 static assert(is(Select!(false, int, long) == long));
8446 static struct Foo {}
8447 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8449 // can select symbols
8450 int a = 1;
8451 int b = 2;
8452 alias selA = Select!(true, a, b);
8453 alias selB = Select!(false, a, b);
8454 assert(selA == 1);
8455 assert(selB == 2);
8457 // can select (compile-time) expressions
8458 enum val = Select!(false, -4, 9 - 6);
8459 static assert(val == 3);
8463 Select one of two functions to run via template parameter.
8465 Params:
8466 cond = A `bool` which determines which function is run
8467 a = The first function
8468 b = The second function
8470 Returns:
8471 `a` without evaluating `b` if `cond` is `true`.
8472 Otherwise, returns `b` without evaluating `a`.
8474 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8475 /// Ditto
8476 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8479 @safe unittest
8481 real run() { return 0; }
8482 int fail() { assert(0); }
8483 auto a = select!true(run(), fail());
8484 auto b = select!false(fail(), run());
8485 static assert(is(typeof(a) == real));
8486 static assert(is(typeof(b) == real));
8490 Determine if a symbol has a given
8491 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8493 See_Also:
8494 $(LREF getUDAs)
8496 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8499 @safe unittest
8501 enum E;
8502 struct S {}
8504 @("alpha") int a;
8505 static assert(hasUDA!(a, "alpha"));
8506 static assert(!hasUDA!(a, S));
8507 static assert(!hasUDA!(a, E));
8509 @(E) int b;
8510 static assert(!hasUDA!(b, "alpha"));
8511 static assert(!hasUDA!(b, S));
8512 static assert(hasUDA!(b, E));
8514 @E int c;
8515 static assert(!hasUDA!(c, "alpha"));
8516 static assert(!hasUDA!(c, S));
8517 static assert(hasUDA!(c, E));
8519 @(S, E) int d;
8520 static assert(!hasUDA!(d, "alpha"));
8521 static assert(hasUDA!(d, S));
8522 static assert(hasUDA!(d, E));
8524 @S int e;
8525 static assert(!hasUDA!(e, "alpha"));
8526 static assert(hasUDA!(e, S));
8527 static assert(!hasUDA!(e, S()));
8528 static assert(!hasUDA!(e, E));
8530 @S() int f;
8531 static assert(!hasUDA!(f, "alpha"));
8532 static assert(hasUDA!(f, S));
8533 static assert(hasUDA!(f, S()));
8534 static assert(!hasUDA!(f, E));
8536 @(S, E, "alpha") int g;
8537 static assert(hasUDA!(g, "alpha"));
8538 static assert(hasUDA!(g, S));
8539 static assert(hasUDA!(g, E));
8541 @(100) int h;
8542 static assert(hasUDA!(h, 100));
8544 struct Named { string name; }
8546 @Named("abc") int i;
8547 static assert(hasUDA!(i, Named));
8548 static assert(hasUDA!(i, Named("abc")));
8549 static assert(!hasUDA!(i, Named("def")));
8551 struct AttrT(T)
8553 string name;
8554 T value;
8557 @AttrT!int("answer", 42) int j;
8558 static assert(hasUDA!(j, AttrT));
8559 static assert(hasUDA!(j, AttrT!int));
8560 static assert(!hasUDA!(j, AttrT!string));
8562 @AttrT!string("hello", "world") int k;
8563 static assert(hasUDA!(k, AttrT));
8564 static assert(!hasUDA!(k, AttrT!int));
8565 static assert(hasUDA!(k, AttrT!string));
8567 struct FuncAttr(alias f) { alias func = f; }
8568 static int fourtyTwo() { return 42; }
8569 static size_t getLen(string s) { return s.length; }
8571 @FuncAttr!getLen int l;
8572 static assert(hasUDA!(l, FuncAttr));
8573 static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8574 static assert(hasUDA!(l, FuncAttr!getLen));
8575 static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8576 static assert(!hasUDA!(l, FuncAttr!getLen()));
8578 @FuncAttr!getLen() int m;
8579 static assert(hasUDA!(m, FuncAttr));
8580 static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8581 static assert(hasUDA!(m, FuncAttr!getLen));
8582 static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8583 static assert(hasUDA!(m, FuncAttr!getLen()));
8587 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8588 from the given symbol.
8590 If the UDA is a type, then any UDAs of the same type on the symbol will
8591 match. If the UDA is a template for a type, then any UDA which is an
8592 instantiation of that template will match. And if the UDA is a value,
8593 then any UDAs on the symbol which are equal to that value will match.
8595 See_Also:
8596 $(LREF hasUDA)
8598 template getUDAs(alias symbol, alias attribute)
8600 import std.meta : Filter;
8602 alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8606 @safe unittest
8608 struct Attr
8610 string name;
8611 int value;
8614 @Attr("Answer", 42) int a;
8615 static assert(getUDAs!(a, Attr).length == 1);
8616 static assert(getUDAs!(a, Attr)[0].name == "Answer");
8617 static assert(getUDAs!(a, Attr)[0].value == 42);
8619 @(Attr("Answer", 42), "string", 9999) int b;
8620 static assert(getUDAs!(b, Attr).length == 1);
8621 static assert(getUDAs!(b, Attr)[0].name == "Answer");
8622 static assert(getUDAs!(b, Attr)[0].value == 42);
8624 @Attr("Answer", 42) @Attr("Pi", 3) int c;
8625 static assert(getUDAs!(c, Attr).length == 2);
8626 static assert(getUDAs!(c, Attr)[0].name == "Answer");
8627 static assert(getUDAs!(c, Attr)[0].value == 42);
8628 static assert(getUDAs!(c, Attr)[1].name == "Pi");
8629 static assert(getUDAs!(c, Attr)[1].value == 3);
8631 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8632 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8633 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8635 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8637 struct AttrT(T)
8639 string name;
8640 T value;
8643 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8644 static assert(getUDAs!(d, AttrT).length == 2);
8645 static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8646 static assert(getUDAs!(d, AttrT)[0].value == 42);
8647 static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8648 static assert(getUDAs!(d, AttrT)[1].value == 3);
8650 static assert(getUDAs!(d, AttrT!uint).length == 1);
8651 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8652 static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8654 static assert(getUDAs!(d, AttrT!int).length == 1);
8655 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8656 static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8658 struct SimpleAttr {}
8660 @SimpleAttr int e;
8661 static assert(getUDAs!(e, SimpleAttr).length == 1);
8662 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8664 @SimpleAttr() int f;
8665 static assert(getUDAs!(f, SimpleAttr).length == 1);
8666 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8668 struct FuncAttr(alias f) { alias func = f; }
8669 static int add42(int v) { return v + 42; }
8670 static string concat(string l, string r) { return l ~ r; }
8672 @FuncAttr!add42 int g;
8673 static assert(getUDAs!(g, FuncAttr).length == 1);
8674 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8676 static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8677 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8679 static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8681 static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8682 static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8684 @FuncAttr!add42() int h;
8685 static assert(getUDAs!(h, FuncAttr).length == 1);
8686 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8688 static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8689 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8691 static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8692 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8694 static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8695 static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8697 @("alpha") @(42) int i;
8698 static assert(getUDAs!(i, "alpha").length == 1);
8699 static assert(getUDAs!(i, "alpha")[0] == "alpha");
8701 static assert(getUDAs!(i, 42).length == 1);
8702 static assert(getUDAs!(i, 42)[0] == 42);
8704 static assert(getUDAs!(i, 'c').length == 0);
8707 private template isDesiredUDA(alias attribute)
8709 template isDesiredUDA(alias toCheck)
8711 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8713 static if (__traits(compiles, toCheck == attribute))
8714 enum isDesiredUDA = toCheck == attribute;
8715 else
8716 enum isDesiredUDA = false;
8718 else static if (is(typeof(toCheck)))
8720 static if (__traits(isTemplate, attribute))
8721 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck));
8722 else
8723 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8725 else static if (__traits(isTemplate, attribute))
8726 enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8727 else
8728 enum isDesiredUDA = is(toCheck == attribute);
8733 Params:
8734 symbol = The aggregate type or module to search
8735 attribute = The user-defined attribute to search for
8737 Returns:
8738 All symbols within `symbol` that have the given UDA `attribute`.
8740 Note:
8741 This is not recursive; it will not search for symbols within symbols such as
8742 nested structs or unions.
8744 template getSymbolsByUDA(alias symbol, alias attribute)
8746 alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8748 // if the symbol itself has the UDA, tack it on to the front of the list
8749 static if (hasUDA!(symbol, attribute))
8750 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8751 else
8752 alias getSymbolsByUDA = membersWithUDA;
8756 @safe unittest
8758 enum Attr;
8759 struct A
8761 @Attr int a;
8762 int b;
8765 static assert(getSymbolsByUDA!(A, Attr).length == 1);
8766 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8770 @safe unittest
8772 enum Attr;
8774 static struct A
8776 @Attr int a;
8777 int b;
8778 @Attr void doStuff() {}
8779 void doOtherStuff() {}
8780 static struct Inner
8782 // Not found by getSymbolsByUDA
8783 @Attr int c;
8787 // Finds both variables and functions with the attribute, but
8788 // doesn't include the variables and functions without it.
8789 static assert(getSymbolsByUDA!(A, Attr).length == 2);
8790 // Can access attributes on the symbols returned by getSymbolsByUDA.
8791 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8792 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8795 /// Finds multiple attributes
8796 @safe unittest
8798 static struct UDA { string name; }
8800 static struct B
8802 @UDA("X")
8803 int x;
8804 @UDA("Y")
8805 int y;
8806 @(100)
8807 int z;
8810 // Finds both UDA attributes.
8811 static assert(getSymbolsByUDA!(B, UDA).length == 2);
8812 // Finds one `100` attribute.
8813 static assert(getSymbolsByUDA!(B, 100).length == 1);
8814 // Can get the value of the UDA from the return value
8815 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8818 /// Checks for UDAs on the aggregate symbol itself
8819 @safe unittest
8821 static struct UDA { string name; }
8823 @UDA("A")
8824 static struct C
8826 @UDA("B")
8827 int d;
8830 static assert(getSymbolsByUDA!(C, UDA).length == 2);
8831 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8832 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8835 /// Finds nothing if there is no member with specific UDA
8836 @safe unittest
8838 static struct UDA { string name; }
8840 static struct D
8842 int x;
8845 static assert(getSymbolsByUDA!(D, UDA).length == 0);
8848 // https://issues.dlang.org/show_bug.cgi?id=18314
8849 @safe unittest
8851 enum attr1;
8852 enum attr2;
8854 struct A
8856 @attr1
8857 int n;
8858 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8859 //@attr1
8860 //void foo()(string){}
8861 @attr1
8862 void foo();
8863 @attr2
8864 void foo(int a);
8867 static assert(getSymbolsByUDA!(A, attr1).length == 2);
8868 static assert(getSymbolsByUDA!(A, attr2).length == 1);
8871 // getSymbolsByUDA fails if type has private members
8872 // https://issues.dlang.org/show_bug.cgi?id=15335
8873 @safe unittest
8875 // HasPrivateMembers has, well, private members, one of which has a UDA.
8876 import std.internal.test.uda : Attr, HasPrivateMembers;
8877 // Trying access to private member from another file therefore we do not have access
8878 // for this otherwise we get deprecation warning - not visible from module
8879 // This line is commented because `__traits(getMember)` should also consider
8880 // private members; this is not currently the case, but the PR that
8881 // fixes `__traits(getMember)` is blocked by this specific test.
8882 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8883 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8886 // getSymbolsByUDA works with structs but fails with classes
8887 // https://issues.dlang.org/show_bug.cgi?id=16387
8888 @safe unittest
8890 enum Attr;
8891 class A
8893 @Attr uint a;
8896 alias res = getSymbolsByUDA!(A, Attr);
8897 static assert(res.length == 1);
8898 static assert(res[0].stringof == "a");
8901 // getSymbolsByUDA fails on AliasSeq members
8902 // https://issues.dlang.org/show_bug.cgi?id=18884
8903 @safe unittest
8905 struct X
8907 alias A = AliasSeq!(ulong, uint);
8910 static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8913 // https://issues.dlang.org/show_bug.cgi?id=23776
8914 @safe pure nothrow @nogc unittest
8916 struct T
8918 struct Tag {}
8919 @Tag struct MyStructA {}
8920 @Tag struct MyStructB {}
8921 @Tag struct MyStructC {}
8923 alias tcomponents = getSymbolsByUDA!(T, T.Tag);
8924 static assert(tcomponents.length > 0);
8926 struct X
8928 struct Tag {}
8929 @Tag enum MyEnumA;
8930 @Tag enum MyEnumB;
8931 @Tag enum MyEnumC;
8933 alias xcomponents = getSymbolsByUDA!(X, X.Tag);
8934 static assert(xcomponents.length > 0);
8937 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8938 // https://issues.dlang.org/show_bug.cgi?id=18624
8939 @safe unittest
8941 enum Attr;
8942 struct A
8944 @Attr void a();
8945 @Attr void a(int n);
8946 void b();
8947 @Attr void c();
8950 alias ola = __traits(getOverloads, A, "a");
8951 static assert(__traits(isSame, getSymbolsByUDA!(A, Attr),
8952 AliasSeq!(ola[0], ola[1], A.c)));
8955 // getSymbolsByUDA no longer works on modules
8956 // https://issues.dlang.org/show_bug.cgi?id=20054
8957 version (StdUnittest)
8959 @("Issue20054")
8960 void issue20054() {}
8961 static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8964 private template isAliasSeq(Args...)
8966 static if (Args.length != 1)
8967 enum isAliasSeq = true;
8968 else
8969 enum isAliasSeq = false;
8972 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8974 import std.meta : Alias, AliasSeq, Filter;
8975 static if (names.length == 0)
8977 alias getSymbolsByUDAImpl = AliasSeq!();
8979 else
8981 alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
8983 // Filtering inaccessible members.
8984 static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
8986 alias getSymbolsByUDAImpl = tail;
8988 else
8990 alias member = __traits(getMember, symbol, names[0]);
8992 // Filtering not compiled members such as alias of basic types.
8993 static if (isAliasSeq!member ||
8994 (isType!member && !isAggregateType!member && !is(member == enum)))
8996 alias getSymbolsByUDAImpl = tail;
8998 // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
8999 else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
9001 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
9002 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
9003 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
9005 else static if (hasUDA!(member, attribute))
9007 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
9009 else
9011 alias getSymbolsByUDAImpl = tail;
9018 Returns: `true` iff all types `Ts` are the same.
9020 enum bool allSameType(Ts...) =
9022 static foreach (T; Ts[Ts.length > 1 .. $])
9023 static if (!is(Ts[0] == T))
9024 if (__ctfe) // Dodge the "statement is unreachable" warning
9025 return false;
9026 return true;
9027 }();
9030 @safe unittest
9032 static assert(allSameType!());
9033 static assert(allSameType!(int));
9034 static assert(allSameType!(int, int));
9035 static assert(allSameType!(int, int, int));
9036 static assert(allSameType!(float, float, float));
9037 static assert(!allSameType!(int, double));
9038 static assert(!allSameType!(int, float, double));
9039 static assert(!allSameType!(int, float, double, real));
9040 static assert(!allSameType!(short, int, float, double, real));
9044 Returns: `true` iff the type `T` can be tested in an $(D
9045 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
9047 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
9050 @safe unittest
9052 class C;
9053 struct S1;
9054 struct S2
9056 T opCast(T)() const;
9059 static assert( ifTestable!bool);
9060 static assert( ifTestable!int);
9061 static assert( ifTestable!(S1*));
9062 static assert( ifTestable!(typeof(null)));
9063 static assert( ifTestable!(int[]));
9064 static assert( ifTestable!(int[string]));
9065 static assert( ifTestable!S2);
9066 static assert( ifTestable!C);
9067 static assert(!ifTestable!S1);
9070 @safe unittest
9072 import std.meta : AliasSeq, allSatisfy;
9073 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
9074 struct BoolWrapper { bool value; }
9075 static assert(!ifTestable!(bool, a => BoolWrapper(a)));
9079 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
9080 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
9082 * Returns:
9083 * `true` if `X` is a type, `false` otherwise
9085 enum isType(alias X) = is(X);
9088 @safe unittest
9090 struct S {
9091 template Test() {}
9093 class C {}
9094 interface I {}
9095 union U {}
9096 static assert(isType!int);
9097 static assert(isType!string);
9098 static assert(isType!(int[int]));
9099 static assert(isType!S);
9100 static assert(isType!C);
9101 static assert(isType!I);
9102 static assert(isType!U);
9104 int n;
9105 void func(){}
9106 static assert(!isType!n);
9107 static assert(!isType!func);
9108 static assert(!isType!(S.Test));
9109 static assert(!isType!(S.Test!()));
9113 * Detect whether symbol or type `X` is a function. This is different that finding
9114 * if a symbol is callable or satisfying `is(X == function)`, it finds
9115 * specifically if the symbol represents a normal function declaration, i.e.
9116 * not a delegate or a function pointer.
9118 * Returns:
9119 * `true` if `X` is a function, `false` otherwise
9121 * See_Also:
9122 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
9123 * respectively.
9125 template isFunction(alias X)
9127 static if (is(typeof(&X) U : U*) && is(U == function) ||
9128 is(typeof(&X) U == delegate))
9130 // x is a (nested) function symbol.
9131 enum isFunction = true;
9133 else static if (is(X T))
9135 // x is a type. Take the type of it and examine.
9136 enum isFunction = is(T == function);
9138 else
9139 enum isFunction = false;
9143 @safe unittest
9145 static void func(){}
9146 static assert(isFunction!func);
9148 struct S
9150 void func(){}
9152 static assert(isFunction!(S.func));
9156 * Detect whether `X` is a final method or class.
9158 * Returns:
9159 * `true` if `X` is final, `false` otherwise
9161 template isFinal(alias X)
9163 static if (is(X == class))
9164 enum isFinal = __traits(isFinalClass, X);
9165 else static if (isFunction!X)
9166 enum isFinal = __traits(isFinalFunction, X);
9167 else
9168 enum isFinal = false;
9172 @safe unittest
9174 class C
9176 void nf() {}
9177 static void sf() {}
9178 final void ff() {}
9180 final class FC { }
9182 static assert(!isFinal!(C));
9183 static assert( isFinal!(FC));
9185 static assert(!isFinal!(C.nf));
9186 static assert(!isFinal!(C.sf));
9187 static assert( isFinal!(C.ff));
9191 + Determines whether the type `S` can be copied.
9192 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9193 + Copying for structs can be disabled by using `@disable this(this)`.
9195 + See also: $(DDSUBLINK spec/traits, isCopyable, `__traits(isCopyable, S)`)
9196 + Params:
9197 + S = The type to check.
9199 + Returns:
9200 + `true` if `S` can be copied. `false` otherwise.
9202 enum isCopyable(S) = __traits(isCopyable, S);
9205 @safe unittest
9207 struct S1 {} // Fine. Can be copied
9208 struct S2 { this(this) {}} // Fine. Can be copied
9209 struct S3 {@disable this(this); } // Not fine. Copying is disabled.
9210 struct S4 {S3 s;} // Not fine. A field has copying disabled.
9212 class C1 {}
9214 static assert( isCopyable!S1);
9215 static assert( isCopyable!S2);
9216 static assert(!isCopyable!S3);
9217 static assert(!isCopyable!S4);
9219 static assert(isCopyable!C1);
9220 static assert(isCopyable!int);
9221 static assert(isCopyable!(int[]));
9225 * The parameter type deduced by IFTI when an expression of type T is passed as
9226 * an argument to a template function.
9228 * For all types other than pointer and slice types, `DeducedParameterType!T`
9229 * is the same as `T`. For pointer and slice types, it is `T` with the
9230 * outer-most layer of qualifiers dropped.
9232 package(std) template DeducedParameterType(T)
9234 static if (is(T == U*, U) || is(T == U[], U))
9235 alias DeducedParameterType = Unqual!T;
9236 else
9237 alias DeducedParameterType = T;
9240 @safe unittest
9242 static assert(is(DeducedParameterType!(const(int)) == const(int)));
9243 static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
9245 static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
9246 static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
9249 @safe unittest
9251 static struct NoCopy
9253 @disable this(this);
9256 static assert(is(DeducedParameterType!NoCopy == NoCopy));
9259 @safe unittest
9261 static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
9264 private auto dip1000Test(int x) {return *&x;}
9265 // We don't use isSafe, because betterC client code needs to instantiate
9266 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9267 // __cmp of two strings, so using it would instantate that here instead. That
9268 // won't do because betterC compilations do not link the Phobos binary in.
9269 package(std) enum dip1000Enabled
9270 = is(typeof(&dip1000Test) : int function(int) @safe);