d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[official-gcc.git] / libphobos / src / std / traits.d
blobbbbca69b22bc618b1644b88db9018df29dc6f8a5
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 * ))
71 * $(TR $(TD Type Constructors) $(TD
72 * $(LREF InoutOf)
73 * $(LREF ConstOf)
74 * $(LREF SharedOf)
75 * $(LREF SharedInoutOf)
76 * $(LREF SharedConstOf)
77 * $(LREF SharedConstInoutOf)
78 * $(LREF ImmutableOf)
79 * $(LREF QualifierOf)
80 * ))
81 * $(TR $(TD Categories of types) $(TD
82 * $(LREF allSameType)
83 * $(LREF ifTestable)
84 * $(LREF isType)
85 * $(LREF isAggregateType)
86 * $(LREF isArray)
87 * $(LREF isAssociativeArray)
88 * $(LREF isAutodecodableString)
89 * $(LREF isBasicType)
90 * $(LREF isBoolean)
91 * $(LREF isBuiltinType)
92 * $(LREF isCopyable)
93 * $(LREF isDynamicArray)
94 * $(LREF isEqualityComparable)
95 * $(LREF isFloatingPoint)
96 * $(LREF isIntegral)
97 * $(LREF isNarrowString)
98 * $(LREF isConvertibleToString)
99 * $(LREF isNumeric)
100 * $(LREF isOrderingComparable)
101 * $(LREF isPointer)
102 * $(LREF isScalarType)
103 * $(LREF isSigned)
104 * $(LREF isSIMDVector)
105 * $(LREF isSomeChar)
106 * $(LREF isSomeString)
107 * $(LREF isStaticArray)
108 * $(LREF isUnsigned)
109 * ))
110 * $(TR $(TD Type behaviours) $(TD
111 * $(LREF isAbstractClass)
112 * $(LREF isAbstractFunction)
113 * $(LREF isCallable)
114 * $(LREF isDelegate)
115 * $(LREF isExpressions)
116 * $(LREF isFinalClass)
117 * $(LREF isFinalFunction)
118 * $(LREF isFunctionPointer)
119 * $(LREF isInstanceOf)
120 * $(LREF isIterable)
121 * $(LREF isMutable)
122 * $(LREF isSomeFunction)
123 * $(LREF isTypeTuple)
124 * ))
125 * $(TR $(TD General Types) $(TD
126 * $(LREF ForeachType)
127 * $(LREF KeyType)
128 * $(LREF Largest)
129 * $(LREF mostNegative)
130 * $(LREF OriginalType)
131 * $(LREF PointerTarget)
132 * $(LREF Signed)
133 * $(LREF Unconst)
134 * $(LREF Unqual)
135 * $(LREF Unsigned)
136 * $(LREF ValueType)
137 * $(LREF Promoted)
138 * ))
139 * $(TR $(TD Misc) $(TD
140 * $(LREF lvalueOf)
141 * $(LREF rvalueOf)
142 * $(LREF Select)
143 * $(LREF select)
144 * ))
145 * $(TR $(TD User-Defined Attributes) $(TD
146 * $(LREF hasUDA)
147 * $(LREF getUDAs)
148 * $(LREF getSymbolsByUDA)
149 * ))
153 * Copyright: Copyright The D Language Foundation 2005 - 2009.
154 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
155 * Authors: $(HTTP digitalmars.com, Walter Bright),
156 * Tomasz Stachowiak (`isExpressions`),
157 * $(HTTP erdani.org, Andrei Alexandrescu),
158 * Shin Fujishiro,
159 * $(HTTP octarineparrot.com, Robert Clipsham),
160 * $(HTTP klickverbot.at, David Nadlinger),
161 * Kenji Hara,
162 * Shoichi Kato
163 * Source: $(PHOBOSSRC std/traits.d)
165 /* Copyright The D Language Foundation 2005 - 2009.
166 * Distributed under the Boost Software License, Version 1.0.
167 * (See accompanying file LICENSE_1_0.txt or copy at
168 * http://www.boost.org/LICENSE_1_0.txt)
170 module std.traits;
172 import std.meta : AliasSeq, allSatisfy, anySatisfy, ApplyLeft;
174 // Legacy inheritance from std.typetuple
175 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797
176 import std.meta : staticMapMeta = staticMap;
177 // TODO: find a way to trigger deprecation warnings
178 //deprecated("staticMap is part of std.meta: Please import std.meta")
179 alias staticMap = staticMapMeta;
181 ///////////////////////////////////////////////////////////////////////////////
182 // Type lists
183 ///////////////////////////////////////////////////////////////////////////////
185 private
187 static if (is(ucent))
189 alias CentTypeList = AliasSeq!(cent, ucent);
190 alias SignedCentTypeList = AliasSeq!(cent);
191 alias UnsignedCentTypeList = AliasSeq!(ucent);
193 else
195 alias CentTypeList = AliasSeq!();
196 alias SignedCentTypeList = AliasSeq!();
197 alias UnsignedCentTypeList = AliasSeq!();
200 alias IntegralTypeList = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList);
201 alias SignedIntTypeList = AliasSeq!(byte, short, int, long, SignedCentTypeList);
202 alias UnsignedIntTypeList = AliasSeq!(ubyte, ushort, uint, ulong, UnsignedCentTypeList);
203 alias FloatingPointTypeList = AliasSeq!(float, double, real);
204 alias ImaginaryTypeList = AliasSeq!(ifloat, idouble, ireal);
205 alias ComplexTypeList = AliasSeq!(cfloat, cdouble, creal);
206 alias NumericTypeList = AliasSeq!(IntegralTypeList, FloatingPointTypeList);
207 alias CharTypeList = AliasSeq!(char, wchar, dchar);
211 * Params:
212 * T = The type to qualify
213 * Returns:
214 * `T` with the `inout` qualifier added.
216 alias InoutOf(T) = inout(T);
219 @safe unittest
221 static assert(is(InoutOf!(int) == inout int));
222 static assert(is(InoutOf!(inout int) == inout int));
223 static assert(is(InoutOf!(const int) == inout const int));
224 static assert(is(InoutOf!(shared int) == inout shared int));
228 * Params:
229 * T = The type to qualify
230 * Returns:
231 * `T` with the `const` qualifier added.
233 alias ConstOf(T) = const(T);
236 @safe unittest
238 static assert(is(ConstOf!(int) == const int));
239 static assert(is(ConstOf!(const int) == const int));
240 static assert(is(ConstOf!(inout int) == const inout int));
241 static assert(is(ConstOf!(shared int) == const shared int));
245 * Params:
246 * T = The type to qualify
247 * Returns:
248 * `T` with the `shared` qualifier added.
250 alias SharedOf(T) = shared(T);
253 @safe unittest
255 static assert(is(SharedOf!(int) == shared int));
256 static assert(is(SharedOf!(shared int) == shared int));
257 static assert(is(SharedOf!(inout int) == shared inout int));
258 static assert(is(SharedOf!(immutable int) == shared immutable int));
262 * Params:
263 * T = The type to qualify
264 * Returns:
265 * `T` with the `inout` and `shared` qualifiers added.
267 alias SharedInoutOf(T) = shared(inout(T));
270 @safe unittest
272 static assert(is(SharedInoutOf!(int) == shared inout int));
273 static assert(is(SharedInoutOf!(int) == inout shared int));
275 static assert(is(SharedInoutOf!(const int) == shared inout const int));
276 static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int));
280 * Params:
281 * T = The type to qualify
282 * Returns:
283 * `T` with the `const` and `shared` qualifiers added.
285 alias SharedConstOf(T) = shared(const(T));
288 @safe unittest
290 static assert(is(SharedConstOf!(int) == shared const int));
291 static assert(is(SharedConstOf!(int) == const shared int));
293 static assert(is(SharedConstOf!(inout int) == shared inout const int));
294 // immutable variables are implicitly shared and const
295 static assert(is(SharedConstOf!(immutable int) == immutable int));
299 * Params:
300 * T = The type to qualify
301 * Returns:
302 * `T` with the `const`, `shared`, and `inout` qualifiers added.
304 alias SharedConstInoutOf(T) = shared(const(inout(T)));
307 @safe unittest
309 static assert(is(SharedConstInoutOf!(int) == shared const inout int));
310 static assert(is(SharedConstInoutOf!(int) == const shared inout int));
311 static assert(is(SharedConstInoutOf!(inout int) == shared inout const int));
312 // immutable variables are implicitly shared and const
313 static assert(is(SharedConstInoutOf!(immutable int) == immutable int));
317 * Params:
318 * T = The type to qualify
319 * Returns:
320 * `T` with the `immutable` qualifier added.
322 alias ImmutableOf(T) = immutable(T);
325 @safe unittest
327 static assert(is(ImmutableOf!(int) == immutable int));
328 static assert(is(ImmutableOf!(const int) == immutable int));
329 static assert(is(ImmutableOf!(inout int) == immutable int));
330 static assert(is(ImmutableOf!(shared int) == immutable int));
333 @safe unittest
335 static assert(is( InoutOf!int == inout int));
336 static assert(is( ConstOf!int == const int));
337 static assert(is( SharedOf!int == shared int));
338 static assert(is(SharedInoutOf!int == shared inout int));
339 static assert(is(SharedConstOf!int == shared const int));
340 static assert(is( ImmutableOf!int == immutable int));
344 * Gives a template that can be used to apply the same
345 * attributes that are on the given type `T`. E.g. passing
346 * `inout shared int` will return `SharedInoutOf`.
348 * Params:
349 * T = the type to check qualifiers from
350 * Returns:
351 * The qualifier template from the given type `T`
353 template QualifierOf(T)
355 static if (is(immutable T == T))
357 alias QualifierOf = ImmutableOf;
359 else
361 private enum quals = is(const T == T) | (is(inout T == T) << 1) | (is(shared T == T) << 2);
362 static if (quals == 0) { import std.meta : Alias; alias QualifierOf = Alias; }
363 else static if (quals == 1) alias QualifierOf = ConstOf;
364 else static if (quals == 2) alias QualifierOf = InoutOf;
365 else static if (quals == 3) alias QualifierOf = ConstInoutOf;
366 else static if (quals == 4) alias QualifierOf = SharedOf;
367 else static if (quals == 5) alias QualifierOf = SharedConstOf;
368 else static if (quals == 6) alias QualifierOf = SharedInoutOf;
369 else alias QualifierOf = SharedConstInoutOf;
374 @safe unittest
376 static assert(__traits(isSame, QualifierOf!(shared const inout int), SharedConstInoutOf));
377 static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf));
378 static assert(__traits(isSame, QualifierOf!(shared int), SharedOf));
379 static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf));
380 import std.meta : Alias;
381 static assert(__traits(isSame, QualifierOf!(int), Alias));
384 @safe unittest
386 alias Qual1 = QualifierOf!( int); static assert(is(Qual1!long == long));
387 alias Qual2 = QualifierOf!( inout int); static assert(is(Qual2!long == inout long));
388 alias Qual3 = QualifierOf!( const int); static assert(is(Qual3!long == const long));
389 alias Qual4 = QualifierOf!(shared int); static assert(is(Qual4!long == shared long));
390 alias Qual5 = QualifierOf!(shared inout int); static assert(is(Qual5!long == shared inout long));
391 alias Qual6 = QualifierOf!(shared const int); static assert(is(Qual6!long == shared const long));
392 alias Qual7 = QualifierOf!( immutable int); static assert(is(Qual7!long == immutable long));
395 version (StdUnittest)
397 import std.meta : Alias;
398 alias TypeQualifierList = AliasSeq!(Alias, ConstOf, SharedOf, SharedConstOf, ImmutableOf);
400 struct SubTypeOf(T)
402 T val;
403 alias val this;
407 private alias parentOf(alias sym) = Identity!(__traits(parent, sym));
408 private alias parentOf(alias sym : T!Args, alias T, Args...) = Identity!(__traits(parent, T));
411 * Get the full package name for the given symbol.
413 template packageName(alias T)
415 import std.algorithm.searching : startsWith;
417 enum bool isNotFunc = !isSomeFunction!(T);
419 static if (__traits(compiles, parentOf!T))
420 enum parent = packageName!(parentOf!T);
421 else
422 enum string parent = null;
424 static if (isNotFunc && T.stringof.startsWith("package "))
425 enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $];
426 else static if (parent)
427 enum packageName = parent;
428 else
429 static assert(false, T.stringof ~ " has no parent");
433 @safe unittest
435 static assert(packageName!packageName == "std");
438 @safe unittest
440 import std.array;
442 static assert(packageName!std == "std");
443 static assert(packageName!(std.traits) == "std"); // this module
444 static assert(packageName!packageName == "std"); // symbol in this module
445 static assert(packageName!(std.array) == "std"); // other module from same package
447 import core.sync.barrier; // local import
448 static assert(packageName!core == "core");
449 static assert(packageName!(core.sync) == "core.sync");
450 static assert(packageName!Barrier == "core.sync");
452 struct X12287(T) { T i; }
453 static assert(packageName!(X12287!int.i) == "std");
456 version (none) @safe unittest //Please uncomment me when changing packageName to test global imports
458 import core.sync.barrier; // global import
459 static assert(packageName!core == "core");
460 static assert(packageName!(core.sync) == "core.sync");
461 static assert(packageName!Barrier == "core.sync");
465 @safe unittest
467 static assert(packageName!moduleName == "std");
470 // https://issues.dlang.org/show_bug.cgi?id=13741
471 @safe unittest
473 import std.ascii : isWhite;
474 static assert(packageName!(isWhite) == "std");
476 struct Foo{void opCall(int){}}
477 static assert(packageName!(Foo.opCall) == "std");
479 @property void function(int) vf;
480 static assert(packageName!(vf) == "std");
484 * Get the module name (including package) for the given symbol.
486 template moduleName(alias T)
488 import std.algorithm.searching : startsWith;
490 enum bool isNotFunc = !isSomeFunction!(T);
492 static if (isNotFunc)
493 static assert(!T.stringof.startsWith("package "),
494 "cannot get the module name for a package");
496 static if (isNotFunc && T.stringof.startsWith("module "))
498 static if (__traits(compiles, packageName!T))
499 enum packagePrefix = packageName!T ~ '.';
500 else
501 enum packagePrefix = "";
503 enum moduleName = packagePrefix ~ T.stringof[7..$];
505 else
506 alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE
510 @safe unittest
512 static assert(moduleName!moduleName == "std.traits");
515 @safe unittest
517 import std.array;
519 static assert(!__traits(compiles, moduleName!std));
520 static assert(moduleName!(std.traits) == "std.traits"); // this module
521 static assert(moduleName!moduleName == "std.traits"); // symbol in this module
522 static assert(moduleName!(std.array) == "std.array"); // other module
523 static assert(moduleName!(std.array.array) == "std.array"); // symbol in other module
525 import core.sync.barrier; // local import
526 static assert(!__traits(compiles, moduleName!(core.sync)));
527 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
528 static assert(moduleName!Barrier == "core.sync.barrier");
530 struct X12287(T) { T i; }
531 static assert(moduleName!(X12287!int.i) == "std.traits");
534 // https://issues.dlang.org/show_bug.cgi?id=13741
535 @safe unittest
537 import std.ascii : isWhite;
538 static assert(moduleName!(isWhite) == "std.ascii");
540 struct Foo{void opCall(int){}}
541 static assert(moduleName!(Foo.opCall) == "std.traits");
543 @property void function(int) vf;
544 static assert(moduleName!(vf) == "std.traits");
547 version (none) @safe unittest //Please uncomment me when changing moduleName to test global imports
549 import core.sync.barrier; // global import
550 static assert(!__traits(compiles, moduleName!(core.sync)));
551 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
552 static assert(moduleName!Barrier == "core.sync.barrier");
555 /***
556 * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.
558 Example:
559 -----------------
560 module myModule;
561 struct MyStruct {}
562 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
563 -----------------
565 enum fullyQualifiedName(T) = fqnType!(T, false, false, false, false);
567 /// ditto
568 enum fullyQualifiedName(alias T) = fqnSym!(T);
571 @safe unittest
573 static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
576 version (StdUnittest)
578 // Used for both fqnType and fqnSym unittests
579 private struct QualifiedNameTests
581 struct Inner
583 bool value;
586 ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 );
587 ref const(Inner[string]) retfunc( return ref Inner var1 );
588 Inner inoutFunc(inout Inner) inout;
589 shared(const(Inner[string])[]) data;
590 const Inner delegate(double, string) @safe nothrow deleg;
591 inout(int) delegate(inout int) inout inoutDeleg;
592 Inner function(out double, string) funcPtr;
593 extern(C) Inner function(double, string) cFuncPtr;
595 extern(C) void cVarArg(int, ...);
596 void dVarArg(...);
597 void dVarArg2(int, ...);
598 void typesafeVarArg(int[] ...);
600 Inner[] array;
601 Inner[16] sarray;
602 Inner[Inner] aarray;
603 const(Inner[const(Inner)]) qualAarray;
605 shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg;
607 struct Data(T) { int x; }
608 void tfunc(T...)(T args) {}
610 template Inst(alias A) { int x; }
612 class Test12309(T, int x, string s) {}
615 private enum QualifiedEnum
617 a = 42
621 private template fqnSym(alias T : X!A, alias X, A...)
623 template fqnTuple(T...)
625 static if (T.length == 0)
626 enum fqnTuple = "";
627 else static if (T.length == 1)
629 static if (isExpressionTuple!T)
630 enum fqnTuple = T[0].stringof;
631 else
632 enum fqnTuple = fullyQualifiedName!(T[0]);
634 else
635 enum fqnTuple = fqnTuple!(T[0]) ~ ", " ~ fqnTuple!(T[1 .. $]);
638 enum fqnSym =
639 fqnSym!(__traits(parent, X)) ~
640 '.' ~ __traits(identifier, X) ~ "!(" ~ fqnTuple!A ~ ")";
643 private template fqnSym(alias T)
645 static if (__traits(compiles, __traits(parent, T)) && !__traits(isSame, T, __traits(parent, T)))
646 enum parentPrefix = fqnSym!(__traits(parent, T)) ~ ".";
647 else
648 enum parentPrefix = null;
650 static string adjustIdent(string s)
652 import std.algorithm.searching : findSplit, skipOver;
654 if (s.skipOver("package ") || s.skipOver("module "))
655 return s;
656 return s.findSplit("(")[0];
658 enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
661 @safe unittest
663 alias fqn = fullyQualifiedName;
665 // Make sure those 2 are the same
666 static assert(fqnSym!fqn == fqn!fqn);
668 static assert(fqn!fqn == "std.traits.fullyQualifiedName");
670 alias qnTests = QualifiedNameTests;
671 enum prefix = "std.traits.QualifiedNameTests.";
672 static assert(fqn!(qnTests.Inner) == prefix ~ "Inner");
673 static assert(fqn!(qnTests.func) == prefix ~ "func");
674 static assert(fqn!(qnTests.Data!int) == prefix ~ "Data!(int)");
675 static assert(fqn!(qnTests.Data!int.x) == prefix ~ "Data!(int).x");
676 static assert(fqn!(qnTests.tfunc!(int[])) == prefix ~ "tfunc!(int[])");
677 static assert(fqn!(qnTests.Inst!(Object)) == prefix ~ "Inst!(object.Object)");
678 static assert(fqn!(qnTests.Inst!(Object).x) == prefix ~ "Inst!(object.Object).x");
680 static assert(fqn!(qnTests.Test12309!(int, 10, "str"))
681 == prefix ~ "Test12309!(int, 10, \"str\")");
683 import core.sync.barrier;
684 static assert(fqn!Barrier == "core.sync.barrier.Barrier");
687 @safe unittest
689 struct TemplatedStruct()
691 enum foo = 0;
693 alias TemplatedStructAlias = TemplatedStruct;
694 assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo));
697 private template fqnType(T,
698 bool alreadyConst, bool alreadyImmutable, bool alreadyShared, bool alreadyInout)
700 // Convenience tags
701 enum {
702 _const = 0,
703 _immutable = 1,
704 _shared = 2,
705 _inout = 3
708 alias qualifiers = AliasSeq!(is(T == const), is(T == immutable), is(T == shared), is(T == inout));
709 alias noQualifiers = AliasSeq!(false, false, false, false);
711 string storageClassesString(uint psc)() @property
713 import std.conv : text;
715 alias PSC = ParameterStorageClass;
717 return text(
718 psc & PSC.scope_ ? "scope " : "",
719 psc & PSC.return_ ? "return " : "",
720 psc & PSC.in_ ? "in " : "",
721 psc & PSC.out_ ? "out " : "",
722 psc & PSC.ref_ ? "ref " : "",
723 psc & PSC.lazy_ ? "lazy " : "",
727 string parametersTypeString(T)() @property
729 alias parameters = Parameters!(T);
730 alias parameterStC = ParameterStorageClassTuple!(T);
732 enum variadic = variadicFunctionStyle!T;
733 static if (variadic == Variadic.no)
734 enum variadicStr = "";
735 else static if (variadic == Variadic.c)
736 enum variadicStr = ", ...";
737 else static if (variadic == Variadic.d)
738 enum variadicStr = parameters.length ? ", ..." : "...";
739 else static if (variadic == Variadic.typesafe)
740 enum variadicStr = " ...";
741 else
742 static assert(0, "New variadic style has been added, please update fullyQualifiedName implementation");
744 static if (parameters.length)
746 import std.algorithm.iteration : map;
747 import std.array : join;
748 import std.meta : staticMap;
749 import std.range : zip;
751 string result = join(
752 map!(a => (a[0] ~ a[1]))(
753 zip([staticMap!(storageClassesString, parameterStC)],
754 [staticMap!(fullyQualifiedName, parameters)])
756 ", "
759 return result ~= variadicStr;
761 else
762 return variadicStr;
765 string linkageString(T)() @property
767 enum linkage = functionLinkage!T;
769 if (linkage != "D")
770 return "extern(" ~ linkage ~ ") ";
771 else
772 return "";
775 string functionAttributeString(T)() @property
777 alias FA = FunctionAttribute;
778 enum attrs = functionAttributes!T;
780 static if (attrs == FA.none)
781 return "";
782 else
783 return
784 (attrs & FA.pure_ ? " pure" : "")
785 ~ (attrs & FA.nothrow_ ? " nothrow" : "")
786 ~ (attrs & FA.ref_ ? " ref" : "")
787 ~ (attrs & FA.property ? " @property" : "")
788 ~ (attrs & FA.trusted ? " @trusted" : "")
789 ~ (attrs & FA.safe ? " @safe" : "")
790 ~ (attrs & FA.nogc ? " @nogc" : "")
791 ~ (attrs & FA.return_ ? " return" : "")
792 ~ (attrs & FA.live ? " @live" : "");
795 string addQualifiers(string typeString,
796 bool addConst, bool addImmutable, bool addShared, bool addInout)
798 auto result = typeString;
799 if (addShared)
801 result = "shared(" ~ result ~")";
803 if (addConst || addImmutable || addInout)
805 result = (addConst ? "const" : addImmutable ? "immutable" : "inout")
806 ~ "(" ~ result ~ ")";
808 return result;
811 // Convenience template to avoid copy-paste
812 template chain(string current)
814 enum chain = addQualifiers(current,
815 qualifiers[_const] && !alreadyConst,
816 qualifiers[_immutable] && !alreadyImmutable,
817 qualifiers[_shared] && !alreadyShared,
818 qualifiers[_inout] && !alreadyInout);
821 static if (is(T == string))
823 enum fqnType = "string";
825 else static if (is(T == wstring))
827 enum fqnType = "wstring";
829 else static if (is(T == dstring))
831 enum fqnType = "dstring";
833 else static if (is(T == typeof(null)))
835 enum fqnType = "typeof(null)";
837 else static if (isBasicType!T && !is(T == enum))
839 enum fqnType = chain!((Unqual!T).stringof);
841 else static if (isAggregateType!T || is(T == enum))
843 enum fqnType = chain!(fqnSym!T);
845 else static if (isStaticArray!T)
847 import std.conv : to;
848 enum fqnType = chain!(
849 fqnType!(typeof(T.init[0]), qualifiers) ~ "[" ~ to!string(T.length) ~ "]"
852 else static if (isArray!T)
854 enum fqnType = chain!(
855 fqnType!(typeof(T.init[0]), qualifiers) ~ "[]"
858 else static if (isAssociativeArray!T)
860 enum fqnType = chain!(
861 fqnType!(ValueType!T, qualifiers) ~ '[' ~ fqnType!(KeyType!T, noQualifiers) ~ ']'
864 else static if (isSomeFunction!T)
866 static if (is(T F == delegate))
868 enum qualifierString =
869 (is(F == shared) ? " shared" : "")
870 ~ (is(F == inout) ? " inout" :
871 is(F == immutable) ? " immutable" :
872 is(F == const) ? " const" : "");
873 enum fqnType = chain!(
874 linkageString!T
875 ~ fqnType!(ReturnType!T, noQualifiers)
876 ~ " delegate(" ~ parametersTypeString!(T) ~ ")"
877 ~ functionAttributeString!T
878 ~ qualifierString
881 else
883 enum fqnType = chain!(
884 linkageString!T
885 ~ fqnType!(ReturnType!T, noQualifiers)
886 ~ (isFunctionPointer!T ? " function(" : "(")
887 ~ parametersTypeString!(T) ~ ")"
888 ~ functionAttributeString!T
892 else static if (is(T == U*, U))
894 enum fqnType = chain!(
895 fqnType!(U, qualifiers) ~ "*"
898 else static if (is(T : __vector(V[N]), V, size_t N))
900 import std.conv : to;
901 enum fqnType = chain!(
902 "__vector(" ~ fqnType!(V, qualifiers) ~ "[" ~ N.to!string ~ "])"
905 else
906 // In case something is forgotten
907 static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string");
910 @safe unittest
912 import std.format : format;
913 alias fqn = fullyQualifiedName;
915 // Verify those 2 are the same for simple case
916 alias Ambiguous = const(QualifiedNameTests.Inner);
917 static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false));
919 // Main tests
920 enum inner_name = "std.traits.QualifiedNameTests.Inner";
921 with (QualifiedNameTests)
923 // Special cases
924 static assert(fqn!(string) == "string");
925 static assert(fqn!(wstring) == "wstring");
926 static assert(fqn!(dstring) == "dstring");
927 static assert(fqn!(typeof(null)) == "typeof(null)");
928 static assert(fqn!(void) == "void");
929 static assert(fqn!(const(void)) == "const(void)");
930 static assert(fqn!(shared(void)) == "shared(void)");
931 static assert(fqn!(shared const(void)) == "const(shared(void))");
932 static assert(fqn!(shared inout(void)) == "inout(shared(void))");
933 static assert(fqn!(shared inout const(void)) == "const(shared(void))");
934 static assert(fqn!(inout(void)) == "inout(void)");
935 static assert(fqn!(inout const(void)) == "const(void)");
936 static assert(fqn!(immutable(void)) == "immutable(void)");
938 // Basic qualified name
939 static assert(fqn!(Inner) == inner_name);
940 static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type
941 static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol
943 // Array types
944 static assert(fqn!(typeof(array)) == format("%s[]", inner_name));
945 static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name));
946 static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name));
948 // qualified key for AA
949 static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name));
951 // Qualified composed data types
952 static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name));
954 // Function types + function attributes
955 static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref",
956 inner_name, inner_name));
957 static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name));
958 static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name));
959 static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name));
960 static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout");
961 static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name));
962 static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name));
964 // Delegate type with qualified function type
965 static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~
966 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name));
968 // Variable argument function types
969 static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)");
970 static assert(fqn!(typeof(dVarArg)) == "void(...)");
971 static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)");
972 static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)");
974 // SIMD vector
975 static if (is(__vector(float[4])))
977 static assert(fqn!(__vector(float[4])) == "__vector(float[4])");
982 /***
983 * Get the type of the return value from a function,
984 * a pointer to function, a delegate, a struct
985 * with an opCall, a pointer to a struct with an opCall,
986 * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
987 * is not part of a type, but the attribute of the function
988 * (see template $(LREF functionAttributes)).
990 * $(NOTE To reduce template instantiations, consider instead using
991 * $(D typeof(() { return func(args); } ())) if the argument types are known or
992 * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
994 template ReturnType(alias func)
995 if (isCallable!func)
997 static if (is(FunctionTypeOf!func R == return))
998 alias ReturnType = R;
999 else
1000 static assert(0, "argument has no return type");
1004 @safe unittest
1006 int foo();
1007 ReturnType!foo x; // x is declared as int
1010 @safe unittest
1012 struct G
1014 int opCall (int i) { return 1;}
1017 alias ShouldBeInt = ReturnType!G;
1018 static assert(is(ShouldBeInt == int));
1020 G g;
1021 static assert(is(ReturnType!g == int));
1023 G* p;
1024 alias pg = ReturnType!p;
1025 static assert(is(pg == int));
1027 class C
1029 int opCall (int i) { return 1;}
1032 static assert(is(ReturnType!C == int));
1034 C c;
1035 static assert(is(ReturnType!c == int));
1037 class Test
1039 int prop() @property { return 0; }
1041 alias R_Test_prop = ReturnType!(Test.prop);
1042 static assert(is(R_Test_prop == int));
1044 alias R_dglit = ReturnType!((int a) { return a; });
1045 static assert(is(R_dglit == int));
1048 /***
1049 Get, as a tuple, the types of the parameters to a function, a pointer
1050 to function, a delegate, a struct with an `opCall`, a pointer to a
1051 struct with an `opCall`, or a class with an `opCall`.
1053 template Parameters(alias func)
1054 if (isCallable!func)
1056 static if (is(FunctionTypeOf!func P == function))
1057 alias Parameters = P;
1058 else
1059 static assert(0, "argument has no parameters");
1063 @safe unittest
1065 int foo(int, long);
1066 void bar(Parameters!foo); // declares void bar(int, long);
1067 void abc(Parameters!foo[1]); // declares void abc(long);
1071 * Alternate name for $(LREF Parameters), kept for legacy compatibility.
1073 alias ParameterTypeTuple = Parameters;
1075 @safe unittest
1077 int foo(int i, bool b) { return 0; }
1078 static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool)));
1079 static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool)));
1081 struct S { real opCall(real r, int i) { return 0.0; } }
1082 S s;
1083 static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int)));
1084 static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int)));
1085 static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int)));
1087 class Test
1089 int prop() @property { return 0; }
1091 alias P_Test_prop = ParameterTypeTuple!(Test.prop);
1092 static assert(P_Test_prop.length == 0);
1094 alias P_dglit = ParameterTypeTuple!((int a){});
1095 static assert(P_dglit.length == 1);
1096 static assert(is(P_dglit[0] == int));
1100 Returns the number of arguments of function `func`.
1101 arity is undefined for variadic functions.
1103 template arity(alias func)
1104 if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
1106 enum size_t arity = Parameters!func.length;
1110 @safe unittest
1112 void foo(){}
1113 static assert(arity!foo == 0);
1114 void bar(uint){}
1115 static assert(arity!bar == 1);
1116 void variadicFoo(uint...){}
1117 static assert(!__traits(compiles, arity!variadicFoo));
1120 // https://issues.dlang.org/show_bug.cgi?id=11389
1121 @safe unittest
1123 alias TheType = size_t function( string[] );
1124 static assert(arity!TheType == 1);
1128 Get tuple, one per function parameter, of the storage classes of the parameters.
1129 Params:
1130 func = function symbol or type of function, delegate, or pointer to function
1131 Returns:
1132 A tuple of ParameterStorageClass bits
1134 enum ParameterStorageClass : uint
1137 * These flags can be bitwise OR-ed together to represent complex storage
1138 * class.
1140 none = 0x00,
1141 in_ = 0x01, /// ditto
1142 ref_ = 0x02, /// ditto
1143 out_ = 0x04, /// ditto
1144 lazy_ = 0x08, /// ditto
1145 scope_ = 0x10, /// ditto
1146 return_ = 0x20, /// ditto
1149 /// ditto
1150 template ParameterStorageClassTuple(alias func)
1151 if (isCallable!func)
1153 alias Func = FunctionTypeOf!func;
1155 static if (is(Func PT == __parameters))
1157 template StorageClass(size_t i)
1159 static if (i < PT.length)
1161 alias StorageClass = AliasSeq!(
1162 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)),
1163 StorageClass!(i + 1));
1165 else
1166 alias StorageClass = AliasSeq!();
1168 alias ParameterStorageClassTuple = StorageClass!0;
1170 else
1172 static assert(0, func[0].stringof ~ " is not a function");
1173 alias ParameterStorageClassTuple = AliasSeq!();
1178 @safe unittest
1180 alias STC = ParameterStorageClass; // shorten the enum name
1182 void func(ref int ctx, out real result, in real param, void* ptr)
1185 alias pstc = ParameterStorageClassTuple!func;
1186 static assert(pstc.length == 4); // number of parameters
1187 static assert(pstc[0] == STC.ref_);
1188 static assert(pstc[1] == STC.out_);
1189 version (none)
1191 // TODO: When the DMD PR (dlang/dmd#11474) gets merged,
1192 // remove the versioning and the second test
1193 static assert(pstc[2] == STC.in_);
1194 // This is the current behavior, before `in` is fixed to not be an alias
1195 static assert(pstc[2] == STC.scope_);
1197 static assert(pstc[3] == STC.none);
1201 Convert the result of `__traits(getParameterStorageClasses)`
1202 to $(LREF ParameterStorageClass) `enum`s.
1204 Params:
1205 Attribs = The return value of `__traits(getParameterStorageClasses)`
1206 Returns:
1207 The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s.
1209 template extractParameterStorageClassFlags(Attribs...)
1211 enum ParameterStorageClass extractParameterStorageClassFlags = ()
1213 auto result = ParameterStorageClass.none;
1214 static if (Attribs.length > 0)
1216 static foreach (attrib; Attribs)
1218 final switch (attrib) with (ParameterStorageClass)
1220 case "scope": result |= scope_; break;
1221 case "in": result |= in_; break;
1222 case "out": result |= out_; break;
1223 case "ref": result |= ref_; break;
1224 case "lazy": result |= lazy_; break;
1225 case "return": result |= return_; break;
1228 /* Mimic behavor of original version of ParameterStorageClassTuple()
1229 * to avoid breaking existing code.
1231 if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
1232 result = ParameterStorageClass.return_;
1234 return result;
1235 }();
1239 @safe unittest
1241 static void func(ref int ctx, out real result);
1243 enum param1 = extractParameterStorageClassFlags!(
1244 __traits(getParameterStorageClasses, func, 0)
1246 static assert(param1 == ParameterStorageClass.ref_);
1248 enum param2 = extractParameterStorageClassFlags!(
1249 __traits(getParameterStorageClasses, func, 1)
1251 static assert(param2 == ParameterStorageClass.out_);
1253 enum param3 = extractParameterStorageClassFlags!(
1254 __traits(getParameterStorageClasses, func, 0),
1255 __traits(getParameterStorageClasses, func, 1)
1257 static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_));
1260 @safe unittest
1262 alias STC = ParameterStorageClass;
1264 void noparam() {}
1265 static assert(ParameterStorageClassTuple!noparam.length == 0);
1267 ref int test(scope int*, ref int, out int, lazy int, int, return ref int i) { return i; }
1268 alias test_pstc = ParameterStorageClassTuple!test;
1269 static assert(test_pstc.length == 6);
1270 static assert(test_pstc[0] == STC.scope_);
1271 static assert(test_pstc[1] == STC.ref_);
1272 static assert(test_pstc[2] == STC.out_);
1273 static assert(test_pstc[3] == STC.lazy_);
1274 static assert(test_pstc[4] == STC.none);
1275 static assert(test_pstc[5] == STC.return_);
1277 interface Test
1279 void test_const(int) const;
1280 void test_sharedconst(int) shared const;
1282 Test testi;
1284 alias test_const_pstc = ParameterStorageClassTuple!(Test.test_const);
1285 static assert(test_const_pstc.length == 1);
1286 static assert(test_const_pstc[0] == STC.none);
1288 alias test_sharedconst_pstc = ParameterStorageClassTuple!(testi.test_sharedconst);
1289 static assert(test_sharedconst_pstc.length == 1);
1290 static assert(test_sharedconst_pstc[0] == STC.none);
1292 alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {});
1293 static assert(dglit_pstc.length == 1);
1294 static assert(dglit_pstc[0] == STC.ref_);
1296 // https://issues.dlang.org/show_bug.cgi?id=9317
1297 static inout(int) func(inout int param) { return param; }
1298 static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none);
1301 @safe unittest
1303 // https://issues.dlang.org/show_bug.cgi?id=14253
1304 static struct Foo {
1305 ref Foo opAssign(ref Foo rhs) return { return this; }
1308 alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]);
1313 Get, as a tuple, the identifiers of the parameters to a function symbol.
1315 template ParameterIdentifierTuple(alias func)
1316 if (isCallable!func)
1318 static if (is(FunctionTypeOf!func PT == __parameters))
1320 template Get(size_t i)
1322 static if (!isFunctionPointer!func && !isDelegate!func
1323 // Unnamed parameters yield CT error.
1324 && is(typeof(__traits(identifier, PT[i .. i+1])))
1325 // Filter out unnamed args, which look like (Type) instead of (Type name).
1326 && PT[i].stringof != PT[i .. i+1].stringof[1..$-1])
1328 enum Get = __traits(identifier, PT[i .. i+1]);
1330 else
1332 enum Get = "";
1336 else
1338 static assert(0, func.stringof ~ " is not a function");
1340 // Define dummy entities to avoid pointless errors
1341 template Get(size_t i) { enum Get = ""; }
1342 alias PT = AliasSeq!();
1345 template Impl(size_t i = 0)
1347 static if (i == PT.length)
1348 alias Impl = AliasSeq!();
1349 else
1350 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1353 alias ParameterIdentifierTuple = Impl!();
1357 @safe unittest
1359 int foo(int num, string name, int);
1360 static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
1363 // https://issues.dlang.org/show_bug.cgi?id=19456
1364 @safe unittest
1366 struct SomeType {}
1367 void foo(SomeType);
1368 void bar(int);
1369 static assert([ParameterIdentifierTuple!foo] == [""]);
1370 static assert([ParameterIdentifierTuple!bar] == [""]);
1373 @safe unittest
1375 alias PIT = ParameterIdentifierTuple;
1377 void bar(int num, string name, int[] array){}
1378 static assert([PIT!bar] == ["num", "name", "array"]);
1380 // might be changed in the future?
1381 void function(int num, string name) fp;
1382 static assert([PIT!fp] == ["", ""]);
1384 // might be changed in the future?
1385 void delegate(int num, string name, int[long] aa) dg;
1386 static assert([PIT!dg] == ["", "", ""]);
1388 interface Test
1390 @property string getter();
1391 @property void setter(int a);
1392 Test method(int a, long b, string c);
1394 static assert([PIT!(Test.getter)] == []);
1395 static assert([PIT!(Test.setter)] == ["a"]);
1396 static assert([PIT!(Test.method)] == ["a", "b", "c"]);
1399 // depends on internal
1400 void baw(int, string, int[]){}
1401 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1403 // depends on internal
1404 void baz(AliasSeq!(int, string, int[]) args){}
1405 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1411 Get, as a tuple, the default value of the parameters to a function symbol.
1412 If a parameter doesn't have the default value, `void` is returned instead.
1414 template ParameterDefaults(alias func)
1415 if (isCallable!func)
1417 alias param_names = ParameterIdentifierTuple!func;
1418 static if (is(FunctionTypeOf!(func) PT == __parameters))
1420 template Get(size_t i)
1422 // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1423 // To avoid a name clash, generate local names that are distinct
1424 // from the parameter name, and mix them in.
1425 enum name = param_names[i];
1426 enum args = "args" ~ (name == "args" ? "_" : "");
1427 enum val = "val" ~ (name == "val" ? "_" : "");
1428 enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1429 mixin("
1430 enum hasDefaultArg = (PT[i .. i+1] " ~ args ~ ") { return true; };
1432 static if (is(typeof(hasDefaultArg())))
1434 mixin("
1435 // workaround scope escape check, see
1436 // https://issues.dlang.org/show_bug.cgi?id=16582
1437 // should use return scope once available
1438 enum get = (PT[i .. i+1] " ~ args ~ ") @trusted
1440 // If the parameter is lazy, we force it to be evaluated
1441 // like this.
1442 auto " ~ val ~ " = " ~ args ~ "[0];
1443 auto " ~ ptr ~ " = &" ~ val ~ ";
1444 return *" ~ ptr ~ ";
1445 };");
1446 enum Get = get();
1448 else
1449 alias Get = void;
1450 // If default arg doesn't exist, returns void instead.
1453 else
1455 static assert(0, func.stringof ~ " is not a function");
1457 // Define dummy entities to avoid pointless errors
1458 template Get(size_t i) { enum Get = ""; }
1459 alias PT = AliasSeq!();
1462 template Impl(size_t i = 0)
1464 static if (i == PT.length)
1465 alias Impl = AliasSeq!();
1466 else
1467 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1470 alias ParameterDefaults = Impl!();
1474 @safe unittest
1476 int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
1477 static assert(is(ParameterDefaults!foo[0] == void));
1478 static assert( ParameterDefaults!foo[1] == "hello");
1479 static assert( ParameterDefaults!foo[2] == [1,2,3]);
1480 static assert( ParameterDefaults!foo[3] == 0);
1483 // https://issues.dlang.org/show_bug.cgi?id=17192
1484 @safe unittest
1486 static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1487 int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1490 alias Voids = ParameterDefaults!func;
1491 static assert(Voids.length == 12);
1492 static foreach (V; Voids) static assert(is(V == void));
1495 // https://issues.dlang.org/show_bug.cgi?id=20182
1496 @safe pure nothrow @nogc unittest
1498 struct S
1500 this(ref S) {}
1503 static assert(__traits(compiles, ParameterDefaults!(S.__ctor)));
1507 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1509 alias ParameterDefaultValueTuple = ParameterDefaults;
1511 @safe unittest
1513 alias PDVT = ParameterDefaultValueTuple;
1515 void bar(int n = 1, string s = "hello"){}
1516 static assert(PDVT!bar.length == 2);
1517 static assert(PDVT!bar[0] == 1);
1518 static assert(PDVT!bar[1] == "hello");
1519 static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello"))));
1521 void baz(int x, int n = 1, string s = "hello"){}
1522 static assert(PDVT!baz.length == 3);
1523 static assert(is(PDVT!baz[0] == void));
1524 static assert( PDVT!baz[1] == 1);
1525 static assert( PDVT!baz[2] == "hello");
1526 static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello"))));
1528 // property functions return empty string
1529 // https://issues.dlang.org/show_bug.cgi?id=10800
1530 @property void foo(int x = 3) { }
1531 static assert(PDVT!foo.length == 1);
1532 static assert(PDVT!foo[0] == 3);
1533 static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3))));
1535 struct Colour
1537 ubyte a,r,g,b;
1539 static immutable Colour white = Colour(255,255,255,255);
1541 // https://issues.dlang.org/show_bug.cgi?id=8106
1542 void bug8106(Colour c = Colour.white) {}
1543 //pragma(msg, PDVT!bug8106);
1544 static assert(PDVT!bug8106[0] == Colour.white);
1545 // https://issues.dlang.org/show_bug.cgi?id=16582
1546 void bug16582(scope int* val = null) {}
1547 static assert(PDVT!bug16582[0] is null);
1552 Returns the FunctionAttribute mask for function `func`.
1554 See_Also:
1555 $(LREF hasFunctionAttributes)
1557 enum FunctionAttribute : uint
1560 * These flags can be bitwise OR-ed together to represent a complex attribute.
1562 none = 0,
1563 pure_ = 1 << 0, /// ditto
1564 nothrow_ = 1 << 1, /// ditto
1565 ref_ = 1 << 2, /// ditto
1566 property = 1 << 3, /// ditto
1567 trusted = 1 << 4, /// ditto
1568 safe = 1 << 5, /// ditto
1569 nogc = 1 << 6, /// ditto
1570 system = 1 << 7, /// ditto
1571 const_ = 1 << 8, /// ditto
1572 immutable_ = 1 << 9, /// ditto
1573 inout_ = 1 << 10, /// ditto
1574 shared_ = 1 << 11, /// ditto
1575 return_ = 1 << 12, /// ditto
1576 scope_ = 1 << 13, /// ditto
1577 live = 1 << 14, /// ditto
1580 /// ditto
1581 template functionAttributes(alias func)
1582 if (isCallable!func)
1584 // @bug: workaround for opCall
1585 alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
1586 func, Unqual!(FunctionTypeOf!func));
1588 enum FunctionAttribute functionAttributes =
1589 extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))();
1593 @safe unittest
1595 alias FA = FunctionAttribute; // shorten the enum name
1597 real func(real x) pure nothrow @safe
1599 return x;
1601 static assert(functionAttributes!func & FA.pure_);
1602 static assert(functionAttributes!func & FA.safe);
1603 static assert(!(functionAttributes!func & FA.trusted)); // not @trusted
1606 @system unittest
1608 alias FA = FunctionAttribute;
1610 struct S
1612 int noF() { return 0; }
1613 int constF() const { return 0; }
1614 int immutableF() immutable { return 0; }
1615 int inoutF() inout { return 0; }
1616 int sharedF() shared { return 0; }
1618 int x;
1619 ref int refF() return { return x; }
1620 int propertyF() @property { return 0; }
1621 int nothrowF() nothrow { return 0; }
1622 int nogcF() @nogc { return 0; }
1624 int systemF() @system { return 0; }
1625 int trustedF() @trusted { return 0; }
1626 int safeF() @safe { return 0; }
1628 int pureF() pure { return 0; }
1630 int liveF() @live { return 0; }
1633 static assert(functionAttributes!(S.noF) == FA.system);
1634 static assert(functionAttributes!(typeof(S.noF)) == FA.system);
1636 static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system));
1637 static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system));
1639 static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system));
1640 static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system));
1642 static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system));
1643 static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system));
1645 static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system));
1646 static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system));
1648 static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_));
1649 static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_));
1651 static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system));
1652 static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system));
1654 static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system));
1655 static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system));
1657 static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system));
1658 static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system));
1660 static assert(functionAttributes!(S.systemF) == FA.system);
1661 static assert(functionAttributes!(typeof(S.systemF)) == FA.system);
1663 static assert(functionAttributes!(S.trustedF) == FA.trusted);
1664 static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted);
1666 static assert(functionAttributes!(S.safeF) == FA.safe);
1667 static assert(functionAttributes!(typeof(S.safeF)) == FA.safe);
1669 static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system));
1670 static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system));
1672 static assert(functionAttributes!(S.liveF) == (FA.live | FA.system));
1673 static assert(functionAttributes!(typeof(S.liveF)) == (FA.live | FA.system));
1675 int pure_nothrow() nothrow pure;
1676 void safe_nothrow() @safe nothrow;
1677 static ref int static_ref_property() @property;
1678 ref int ref_property() @property;
1680 static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system));
1681 static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system));
1683 static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_));
1684 static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_));
1686 static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system));
1687 static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system));
1689 static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system));
1690 static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system));
1692 struct S2
1694 int pure_const() const pure { return 0; }
1695 int pure_sharedconst() const shared pure { return 0; }
1698 static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system));
1699 static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system));
1701 static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1702 static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1704 static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1705 static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1707 auto safeDel = delegate() @safe { };
1708 static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1709 static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1711 auto trustedDel = delegate() @trusted { };
1712 static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1713 static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1715 auto systemDel = delegate() @system { };
1716 static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1717 static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1720 private FunctionAttribute extractAttribFlags(Attribs...)()
1722 auto res = FunctionAttribute.none;
1724 static foreach (attrib; Attribs)
1726 switch (attrib) with (FunctionAttribute)
1728 case "pure": res |= pure_; break;
1729 case "nothrow": res |= nothrow_; break;
1730 case "ref": res |= ref_; break;
1731 case "@property": res |= property; break;
1732 case "@trusted": res |= trusted; break;
1733 case "@safe": res |= safe; break;
1734 case "@nogc": res |= nogc; break;
1735 case "@system": res |= system; break;
1736 case "const": res |= const_; break;
1737 case "immutable": res |= immutable_; break;
1738 case "inout": res |= inout_; break;
1739 case "shared": res |= shared_; break;
1740 case "return": res |= return_; break;
1741 case "scope": res |= scope_; break;
1742 case "@live": res |= live; break;
1743 default: assert(0, attrib);
1747 return res;
1751 Checks whether a function has the given attributes attached.
1753 Params:
1754 args = Function to check, followed by a
1755 variadic number of function attributes as strings
1757 Returns:
1758 `true`, if the function has the list of attributes attached and `false` otherwise.
1760 See_Also:
1761 $(LREF functionAttributes)
1763 template hasFunctionAttributes(args...)
1764 if (args.length > 0 && isCallable!(args[0])
1765 && allSatisfy!(isSomeString, typeof(args[1 .. $])))
1767 enum bool hasFunctionAttributes = {
1768 import std.algorithm.searching : canFind;
1769 import std.range : only;
1770 enum funcAttribs = only(__traits(getFunctionAttributes, args[0]));
1771 static foreach (attribute; args[1 .. $])
1773 if (!funcAttribs.canFind(attribute))
1774 return false;
1776 return true;
1777 }();
1781 @safe unittest
1783 real func(real x) pure nothrow @safe;
1784 static assert(hasFunctionAttributes!(func, "@safe", "pure"));
1785 static assert(!hasFunctionAttributes!(func, "@trusted"));
1787 // for templates attributes are automatically inferred
1788 bool myFunc(T)(T b)
1790 return !b;
1792 static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
1793 static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
1796 @system unittest
1798 struct S
1800 int noF();
1801 int constF() const;
1802 int immutableF() immutable;
1803 int inoutF() inout;
1804 int sharedF() shared;
1806 ref int refF() return;
1807 int propertyF() @property;
1808 int nothrowF() nothrow;
1809 int nogcF() @nogc;
1811 int systemF() @system;
1812 int trustedF() @trusted;
1813 int safeF() @safe;
1815 int pureF() pure;
1817 int liveF() @live;
1820 // true if no args passed
1821 static assert(hasFunctionAttributes!(S.noF));
1823 static assert(hasFunctionAttributes!(S.noF, "@system"));
1824 static assert(hasFunctionAttributes!(typeof(S.noF), "@system"));
1825 static assert(!hasFunctionAttributes!(S.noF, "@system", "pure"));
1827 static assert(hasFunctionAttributes!(S.constF, "const", "@system"));
1828 static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system"));
1829 static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc"));
1831 static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system"));
1832 static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system"));
1833 static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure"));
1835 static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system"));
1836 static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system"));
1837 static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure"));
1839 static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system"));
1840 static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system"));
1841 static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted"));
1843 static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return"));
1844 static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return"));
1845 static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure"));
1847 static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system"));
1848 static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system"));
1849 static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref"));
1851 static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system"));
1852 static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system"));
1853 static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted"));
1855 static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system"));
1856 static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system"));
1857 static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref"));
1859 static assert(hasFunctionAttributes!(S.systemF, "@system"));
1860 static assert(hasFunctionAttributes!(typeof(S.systemF), "@system"));
1861 static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref"));
1863 static assert(hasFunctionAttributes!(S.trustedF, "@trusted"));
1864 static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted"));
1865 static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe"));
1867 static assert(hasFunctionAttributes!(S.safeF, "@safe"));
1868 static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe"));
1869 static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow"));
1871 static assert(hasFunctionAttributes!(S.pureF, "pure", "@system"));
1872 static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system"));
1873 static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref"));
1875 static assert(hasFunctionAttributes!(S.liveF, "@live", "@system"));
1876 static assert(hasFunctionAttributes!(typeof(S.liveF), "@live", "@system"));
1877 static assert(!hasFunctionAttributes!(S.liveF, "@live", "@system", "ref"));
1879 int pure_nothrow() nothrow pure { return 0; }
1880 void safe_nothrow() @safe nothrow { }
1881 static ref int static_ref_property() @property { return *(new int); }
1882 ref int ref_property() @property { return *(new int); }
1884 static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe"));
1885 static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe"));
1886 static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted"));
1888 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow"));
1889 static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow"));
1890 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure"));
1891 static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted"));
1893 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe"));
1894 static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe"));
1895 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow"));
1896 static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc"));
1898 static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe"));
1899 static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe"));
1900 static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc"));
1902 struct S2
1904 int pure_const() const pure { return 0; }
1905 int pure_sharedconst() const shared pure { return 0; }
1908 static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system"));
1909 static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system"));
1910 static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref"));
1912 static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system"));
1913 static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system"));
1914 static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc"));
1916 static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe"));
1917 static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe"));
1918 static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1920 auto safeDel = delegate() @safe { };
1921 static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe"));
1922 static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe"));
1923 static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system"));
1925 auto trustedDel = delegate() @trusted { };
1926 static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted"));
1927 static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted"));
1928 static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1930 auto systemDel = delegate() @system { };
1931 static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system"));
1932 static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system"));
1933 static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property"));
1936 // call functions to make CodeCov happy
1938 assert(pure_nothrow == 0);
1939 safe_nothrow;
1940 assert(static_ref_property == 0);
1941 assert(ref_property == 0);
1942 assert(S2().pure_const == 0);
1943 assert((shared S2()).pure_sharedconst == 0);
1944 cast(void) safeDel;
1945 cast(void) trustedDel;
1946 cast(void) systemDel;
1951 `true` if `func` is `@safe` or `@trusted`.
1953 template isSafe(alias func)
1954 if (isCallable!func)
1956 enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 ||
1957 (functionAttributes!func & FunctionAttribute.trusted) != 0;
1961 @safe unittest
1963 @safe int add(int a, int b) {return a+b;}
1964 @trusted int sub(int a, int b) {return a-b;}
1965 @system int mul(int a, int b) {return a*b;}
1967 static assert( isSafe!add);
1968 static assert( isSafe!sub);
1969 static assert(!isSafe!mul);
1973 @safe unittest
1975 //Member functions
1976 interface Set
1978 int systemF() @system;
1979 int trustedF() @trusted;
1980 int safeF() @safe;
1982 static assert( isSafe!(Set.safeF));
1983 static assert( isSafe!(Set.trustedF));
1984 static assert(!isSafe!(Set.systemF));
1986 //Functions
1987 @safe static void safeFunc() {}
1988 @trusted static void trustedFunc() {}
1989 @system static void systemFunc() {}
1991 static assert( isSafe!safeFunc);
1992 static assert( isSafe!trustedFunc);
1993 static assert(!isSafe!systemFunc);
1995 //Delegates
1996 auto safeDel = delegate() @safe {};
1997 auto trustedDel = delegate() @trusted {};
1998 auto systemDel = delegate() @system {};
2000 static assert( isSafe!safeDel);
2001 static assert( isSafe!trustedDel);
2002 static assert(!isSafe!systemDel);
2004 //Lambdas
2005 static assert( isSafe!({safeDel();}));
2006 static assert( isSafe!({trustedDel();}));
2007 static assert(!isSafe!({systemDel();}));
2009 //Static opCall
2010 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
2011 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
2012 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
2014 static assert( isSafe!(SafeStatic()));
2015 static assert( isSafe!(TrustedStatic()));
2016 static assert(!isSafe!(SystemStatic()));
2018 //Non-static opCall
2019 struct Safe { @safe Safe opCall() { return Safe.init; } }
2020 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
2021 struct System { @system System opCall() { return System.init; } }
2023 static assert( isSafe!(Safe.init()));
2024 static assert( isSafe!(Trusted.init()));
2025 static assert(!isSafe!(System.init()));
2030 `true` if `func` is `@system`.
2032 template isUnsafe(alias func)
2034 enum isUnsafe = !isSafe!func;
2038 @safe unittest
2040 @safe int add(int a, int b) {return a+b;}
2041 @trusted int sub(int a, int b) {return a-b;}
2042 @system int mul(int a, int b) {return a*b;}
2044 static assert(!isUnsafe!add);
2045 static assert(!isUnsafe!sub);
2046 static assert( isUnsafe!mul);
2049 @safe unittest
2051 //Member functions
2052 interface Set
2054 int systemF() @system;
2055 int trustedF() @trusted;
2056 int safeF() @safe;
2058 static assert(!isUnsafe!(Set.safeF));
2059 static assert(!isUnsafe!(Set.trustedF));
2060 static assert( isUnsafe!(Set.systemF));
2062 //Functions
2063 @safe static void safeFunc() {}
2064 @trusted static void trustedFunc() {}
2065 @system static void systemFunc() {}
2067 static assert(!isUnsafe!safeFunc);
2068 static assert(!isUnsafe!trustedFunc);
2069 static assert( isUnsafe!systemFunc);
2071 //Delegates
2072 auto safeDel = delegate() @safe {};
2073 auto trustedDel = delegate() @trusted {};
2074 auto systemDel = delegate() @system {};
2076 static assert(!isUnsafe!safeDel);
2077 static assert(!isUnsafe!trustedDel);
2078 static assert( isUnsafe!systemDel);
2080 //Lambdas
2081 static assert(!isUnsafe!({safeDel();}));
2082 static assert(!isUnsafe!({trustedDel();}));
2083 static assert( isUnsafe!({systemDel();}));
2085 //Static opCall
2086 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
2087 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
2088 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
2090 static assert(!isUnsafe!(SafeStatic()));
2091 static assert(!isUnsafe!(TrustedStatic()));
2092 static assert( isUnsafe!(SystemStatic()));
2094 //Non-static opCall
2095 struct Safe { @safe Safe opCall() { return Safe.init; } }
2096 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
2097 struct System { @system System opCall() { return System.init; } }
2099 static assert(!isUnsafe!(Safe.init()));
2100 static assert(!isUnsafe!(Trusted.init()));
2101 static assert( isUnsafe!(System.init()));
2106 Determine the linkage attribute of the function.
2107 Params:
2108 func = the function symbol, or the type of a function, delegate, or pointer to function
2109 Returns:
2110 one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
2112 template functionLinkage(alias func)
2113 if (isCallable!func)
2115 enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
2119 @safe unittest
2121 extern(D) void Dfunc() {}
2122 extern(C) void Cfunc() {}
2123 static assert(functionLinkage!Dfunc == "D");
2124 static assert(functionLinkage!Cfunc == "C");
2126 string a = functionLinkage!Dfunc;
2127 assert(a == "D");
2129 auto fp = &Cfunc;
2130 string b = functionLinkage!fp;
2131 assert(b == "C");
2134 @safe unittest
2136 interface Test
2138 void const_func() const;
2139 void sharedconst_func() shared const;
2141 static assert(functionLinkage!(Test.const_func) == "D");
2142 static assert(functionLinkage!(Test.sharedconst_func) == "D");
2144 static assert(functionLinkage!((int a){}) == "D");
2149 Determines what kind of variadic parameters function has.
2150 Params:
2151 func = function symbol or type of function, delegate, or pointer to function
2152 Returns:
2153 enum Variadic
2155 enum Variadic
2157 /// Function is not variadic.
2159 /// Function is a _C-style variadic function, which uses
2160 /// `core.stdc.stdarg`
2162 /// Function is a _D-style variadic function, which uses
2163 /// `__argptr` and `__arguments`.
2165 /// Function is a typesafe variadic function.
2166 typesafe,
2169 /// ditto
2170 template variadicFunctionStyle(alias func)
2171 if (isCallable!func)
2173 enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
2174 enum Variadic variadicFunctionStyle =
2175 (varargs == "stdarg") ? Variadic.c :
2176 (varargs == "argptr") ? Variadic.d :
2177 (varargs == "typesafe") ? Variadic.typesafe :
2178 (varargs == "none") ? Variadic.no : Variadic.no;
2182 @safe unittest
2184 void func() {}
2185 static assert(variadicFunctionStyle!func == Variadic.no);
2187 extern(C) int printf(in char*, ...);
2188 static assert(variadicFunctionStyle!printf == Variadic.c);
2191 @safe unittest
2193 import core.vararg;
2195 extern(D) void novar() {}
2196 extern(C) void cstyle(int, ...) {}
2197 extern(D) void dstyle(...) {}
2198 extern(D) void typesafe(int[]...) {}
2200 static assert(variadicFunctionStyle!novar == Variadic.no);
2201 static assert(variadicFunctionStyle!cstyle == Variadic.c);
2202 static assert(variadicFunctionStyle!dstyle == Variadic.d);
2203 static assert(variadicFunctionStyle!typesafe == Variadic.typesafe);
2205 static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe);
2210 Get the function type from a callable object `func`.
2212 Using builtin `typeof` on a property function yields the types of the
2213 property value, not of the property function itself. Still,
2214 `FunctionTypeOf` is able to obtain function types of properties.
2216 Note:
2217 Do not confuse function types with function pointer types; function types are
2218 usually used for compile-time reflection purposes.
2220 template FunctionTypeOf(alias func)
2221 if (isCallable!func)
2223 static if ((is(typeof(& func) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func) Fsym == delegate))
2225 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
2227 else static if (is(typeof(& func.opCall) Fobj == delegate) || is(typeof(& func.opCall!()) Fobj == delegate))
2229 alias FunctionTypeOf = Fobj; // HIT: callable object
2231 else static if (
2232 (is(typeof(& func.opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
2233 (is(typeof(& func.opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
2236 alias FunctionTypeOf = Ftyp; // HIT: callable type
2238 else static if (is(func T) || is(typeof(func) T))
2240 static if (is(T == function))
2241 alias FunctionTypeOf = T; // HIT: function
2242 else static if (is(T Fptr : Fptr*) && is(Fptr == function))
2243 alias FunctionTypeOf = Fptr; // HIT: function pointer
2244 else static if (is(T Fdlg == delegate))
2245 alias FunctionTypeOf = Fdlg; // HIT: delegate
2246 else
2247 static assert(0);
2249 else
2250 static assert(0);
2254 @safe unittest
2256 class C
2258 int value() @property { return 0; }
2260 static assert(is( typeof(C.value) == int ));
2261 static assert(is( FunctionTypeOf!(C.value) == function ));
2264 @system unittest
2266 int test(int a);
2267 int propGet() @property;
2268 int propSet(int a) @property;
2269 int function(int) test_fp;
2270 int delegate(int) test_dg;
2271 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) ));
2272 static assert(is( typeof(test) == FunctionTypeOf!test ));
2273 static assert(is( typeof(test) == FunctionTypeOf!test_fp ));
2274 static assert(is( typeof(test) == FunctionTypeOf!test_dg ));
2275 alias int GetterType() @property;
2276 alias int SetterType(int) @property;
2277 static assert(is( FunctionTypeOf!propGet == GetterType ));
2278 static assert(is( FunctionTypeOf!propSet == SetterType ));
2280 interface Prop { int prop() @property; }
2281 Prop prop;
2282 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType ));
2283 static assert(is( FunctionTypeOf!(prop.prop) == GetterType ));
2285 class Callable { int opCall(int) { return 0; } }
2286 auto call = new Callable;
2287 static assert(is( FunctionTypeOf!call == typeof(test) ));
2289 struct StaticCallable { static int opCall(int) { return 0; } }
2290 StaticCallable stcall_val;
2291 StaticCallable* stcall_ptr;
2292 static assert(is( FunctionTypeOf!stcall_val == typeof(test) ));
2293 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) ));
2295 struct TemplatedOpCallF { int opCall()(int) { return 0; } }
2296 static assert(is( FunctionTypeOf!TemplatedOpCallF == typeof(TemplatedOpCallF.opCall!()) ));
2298 int foovar;
2299 struct TemplatedOpCallDg { int opCall()() { return foovar; } }
2300 static assert(is( FunctionTypeOf!TemplatedOpCallDg == typeof(TemplatedOpCallDg.opCall!()) ));
2302 interface Overloads
2304 void test(string);
2305 real test(real);
2306 int test(int);
2307 int test() @property;
2309 alias ov = __traits(getVirtualMethods, Overloads, "test");
2310 alias F_ov0 = FunctionTypeOf!(ov[0]);
2311 alias F_ov1 = FunctionTypeOf!(ov[1]);
2312 alias F_ov2 = FunctionTypeOf!(ov[2]);
2313 alias F_ov3 = FunctionTypeOf!(ov[3]);
2314 static assert(is(F_ov0* == void function(string)));
2315 static assert(is(F_ov1* == real function(real)));
2316 static assert(is(F_ov2* == int function(int)));
2317 static assert(is(F_ov3* == int function() @property));
2319 alias F_dglit = FunctionTypeOf!((int a){ return a; });
2320 static assert(is(F_dglit* : int function(int)));
2324 * Constructs a new function or delegate type with the same basic signature
2325 * as the given one, but different attributes (including linkage).
2327 * This is especially useful for adding/removing attributes to/from types in
2328 * generic code, where the actual type name cannot be spelt out.
2330 * Params:
2331 * T = The base type.
2332 * linkage = The desired linkage of the result type.
2333 * attrs = The desired $(LREF FunctionAttribute)s of the result type.
2335 template SetFunctionAttributes(T, string linkage, uint attrs)
2336 if (isFunctionPointer!T || isDelegate!T)
2338 mixin({
2339 import std.algorithm.searching : canFind;
2341 static assert(!(attrs & FunctionAttribute.trusted) ||
2342 !(attrs & FunctionAttribute.safe),
2343 "Cannot have a function/delegate that is both trusted and safe.");
2345 static immutable linkages = ["D", "C", "Windows", "C++", "System"];
2346 static assert(canFind(linkages, linkage), "Invalid linkage '" ~
2347 linkage ~ "', must be one of " ~ linkages.stringof ~ ".");
2349 string result = "alias ";
2351 static if (linkage != "D")
2352 result ~= "extern(" ~ linkage ~ ") ";
2354 static if (attrs & FunctionAttribute.ref_)
2355 result ~= "ref ";
2357 result ~= "ReturnType!T";
2359 static if (isDelegate!T)
2360 result ~= " delegate";
2361 else
2362 result ~= " function";
2364 result ~= "(";
2366 static if (Parameters!T.length > 0)
2367 result ~= "Parameters!T";
2369 enum varStyle = variadicFunctionStyle!T;
2370 static if (varStyle == Variadic.c)
2371 result ~= ", ...";
2372 else static if (varStyle == Variadic.d)
2373 result ~= "...";
2374 else static if (varStyle == Variadic.typesafe)
2375 result ~= "...";
2377 result ~= ")";
2379 static if (attrs & FunctionAttribute.pure_)
2380 result ~= " pure";
2381 static if (attrs & FunctionAttribute.nothrow_)
2382 result ~= " nothrow";
2383 static if (attrs & FunctionAttribute.property)
2384 result ~= " @property";
2385 static if (attrs & FunctionAttribute.trusted)
2386 result ~= " @trusted";
2387 static if (attrs & FunctionAttribute.safe)
2388 result ~= " @safe";
2389 static if (attrs & FunctionAttribute.nogc)
2390 result ~= " @nogc";
2391 static if (attrs & FunctionAttribute.system)
2392 result ~= " @system";
2393 static if (attrs & FunctionAttribute.const_)
2394 result ~= " const";
2395 static if (attrs & FunctionAttribute.immutable_)
2396 result ~= " immutable";
2397 static if (attrs & FunctionAttribute.inout_)
2398 result ~= " inout";
2399 static if (attrs & FunctionAttribute.shared_)
2400 result ~= " shared";
2401 static if (attrs & FunctionAttribute.return_)
2402 result ~= " return";
2403 static if (attrs & FunctionAttribute.live)
2404 result ~= " @live";
2406 result ~= " SetFunctionAttributes;";
2407 return result;
2408 }());
2411 /// Ditto
2412 template SetFunctionAttributes(T, string linkage, uint attrs)
2413 if (is(T == function))
2415 // To avoid a lot of syntactic headaches, we just use the above version to
2416 // operate on the corresponding function pointer type and then remove the
2417 // indirection again.
2418 alias SetFunctionAttributes = FunctionTypeOf!(SetFunctionAttributes!(T*, linkage, attrs));
2422 @safe unittest
2424 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
2426 auto assumePure(T)(T t)
2427 if (isFunctionPointer!T || isDelegate!T)
2429 enum attrs = functionAttributes!T | FunctionAttribute.pure_;
2430 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
2433 int f()
2435 import core.thread : getpid;
2436 return getpid();
2439 int g() pure @trusted
2441 auto pureF = assumePure(&f);
2442 return pureF();
2444 assert(g() > 0);
2447 version (StdUnittest)
2449 private:
2450 // Some function types to test.
2451 int sc(scope int, ref int, out int, lazy int, int);
2452 extern(System) int novar();
2453 extern(C) int cstyle(int, ...);
2454 extern(D) int dstyle(...);
2455 extern(D) int typesafe(int[]...);
2457 @safe unittest
2459 import std.algorithm.iteration : reduce;
2461 alias FA = FunctionAttribute;
2462 static foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle),
2463 typeof(&dstyle), typeof(&typesafe)))
2465 static foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT))
2467 enum linkage = functionLinkage!T;
2468 enum attrs = functionAttributes!T;
2470 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T),
2471 "Identity check failed for: " ~ T.stringof);
2473 // Check that all linkage types work (D-style variadics require D linkage).
2474 static if (variadicFunctionStyle!T != Variadic.d)
2476 static foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++"))
2478 alias New = SetFunctionAttributes!(T, newLinkage, attrs);
2479 static assert(functionLinkage!New == newLinkage,
2480 "Linkage test failed for: " ~ T.stringof ~ ", " ~ newLinkage ~
2481 " (got " ~ New.stringof ~ ")");
2485 // Add @safe.
2486 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe);
2487 static assert(functionAttributes!T1 == FA.safe);
2489 // Add all known attributes, excluding conflicting ones.
2490 enum allAttrs = reduce!"a | b"([EnumMembers!FA])
2491 & ~FA.safe & ~FA.property & ~FA.const_ & ~FA.immutable_ & ~FA.inout_
2492 & ~FA.shared_ & ~FA.system & ~FA.return_ & ~FA.scope_;
2494 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs);
2495 static assert(functionAttributes!T2 == allAttrs);
2497 // Strip all attributes again.
2498 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none);
2499 static assert(is(T3 == T));
2505 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2506 // Aggregate Types
2507 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2510 Determines whether `T` is a class nested inside another class
2511 and that `T.outer` is the implicit reference to the outer class
2512 (i.e. `outer` has not been used as a field or method name)
2514 Params:
2515 T = type to test
2517 Returns:
2518 `true` if `T` is a class nested inside another, with the conditions described above;
2519 `false` otherwise
2521 template isInnerClass(T)
2522 if (is(T == class))
2524 static if (is(typeof(T.outer)))
2526 bool hasOuterMember(string[] members...)
2528 foreach (m; members)
2530 if (m == "outer")
2531 return true;
2533 return false;
2535 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) &&
2536 !hasOuterMember(__traits(allMembers, T));
2538 else
2539 enum isInnerClass = false;
2543 @safe unittest
2545 class C
2547 int outer;
2549 static assert(!isInnerClass!C);
2551 class Outer1
2553 class Inner1 { }
2554 class Inner2
2556 int outer;
2559 static assert(isInnerClass!(Outer1.Inner1));
2560 static assert(!isInnerClass!(Outer1.Inner2));
2562 static class Outer2
2564 static class Inner
2566 int outer;
2569 static assert(!isInnerClass!(Outer2.Inner));
2573 Determines whether `T` has its own context pointer.
2574 `T` must be either `class`, `struct`, or `union`.
2576 template isNested(T)
2577 if (is(T == class) || is(T == struct) || is(T == union))
2579 enum isNested = __traits(isNested, T);
2583 @safe unittest
2585 static struct S { }
2586 static assert(!isNested!S);
2588 int i;
2589 struct NestedStruct { void f() { ++i; } }
2590 static assert(isNested!NestedStruct);
2594 Determines whether `T` or any of its representation types
2595 have a context pointer.
2597 template hasNested(T)
2599 import std.meta : Filter;
2601 static if (isStaticArray!T && T.length)
2602 enum hasNested = hasNested!(typeof(T.init[0]));
2603 else static if (is(T == class) || is(T == struct) || is(T == union))
2605 // prevent infinite recursion for class with member of same type
2606 enum notSame(U) = !is(immutable T == immutable U);
2607 enum hasNested = isNested!T ||
2608 anySatisfy!(.hasNested, Filter!(notSame, Fields!T));
2610 else
2611 enum hasNested = false;
2615 @safe unittest
2617 static struct S { }
2619 int i;
2620 struct NS { void f() { ++i; } }
2622 static assert(!hasNested!(S[2]));
2623 static assert(hasNested!(NS[2]));
2626 @safe unittest
2628 static assert(!__traits(compiles, isNested!int));
2629 static assert(!hasNested!int);
2631 static struct StaticStruct { }
2632 static assert(!isNested!StaticStruct);
2633 static assert(!hasNested!StaticStruct);
2635 int i;
2636 struct NestedStruct { void f() { ++i; } }
2637 static assert( isNested!NestedStruct);
2638 static assert( hasNested!NestedStruct);
2639 static assert( isNested!(immutable NestedStruct));
2640 static assert( hasNested!(immutable NestedStruct));
2642 static assert(!__traits(compiles, isNested!(NestedStruct[1])));
2643 static assert( hasNested!(NestedStruct[1]));
2644 static assert(!hasNested!(NestedStruct[0]));
2646 struct S1 { NestedStruct nested; }
2647 static assert(!isNested!S1);
2648 static assert( hasNested!S1);
2650 static struct S2 { NestedStruct nested; }
2651 static assert(!isNested!S2);
2652 static assert( hasNested!S2);
2654 static struct S3 { NestedStruct[0] nested; }
2655 static assert(!isNested!S3);
2656 static assert(!hasNested!S3);
2658 static union U { NestedStruct nested; }
2659 static assert(!isNested!U);
2660 static assert( hasNested!U);
2662 static class StaticClass { }
2663 static assert(!isNested!StaticClass);
2664 static assert(!hasNested!StaticClass);
2666 class NestedClass { void f() { ++i; } }
2667 static assert( isNested!NestedClass);
2668 static assert( hasNested!NestedClass);
2669 static assert( isNested!(immutable NestedClass));
2670 static assert( hasNested!(immutable NestedClass));
2672 static assert(!__traits(compiles, isNested!(NestedClass[1])));
2673 static assert( hasNested!(NestedClass[1]));
2674 static assert(!hasNested!(NestedClass[0]));
2676 static class A
2678 A a;
2680 static assert(!hasNested!A);
2684 /***
2685 * Get as a tuple the types of the fields of a struct, class, or union.
2686 * This consists of the fields that take up memory space,
2687 * excluding the hidden fields like the virtual function
2688 * table pointer or a context pointer for nested types.
2689 * If `T` isn't a struct, class, interface or union returns a tuple
2690 * with one element `T`.
2692 * History:
2693 * - Returned `AliasSeq!(Interface)` for interfaces prior to 2.097
2695 template Fields(T)
2697 import core.internal.traits : _Fields = Fields;
2698 alias Fields = _Fields!T;
2702 @safe unittest
2704 import std.meta : AliasSeq;
2705 struct S { int x; float y; }
2706 static assert(is(Fields!S == AliasSeq!(int, float)));
2710 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2712 alias FieldTypeTuple = Fields;
2714 @safe unittest
2716 static assert(is(FieldTypeTuple!int == AliasSeq!int));
2718 static struct StaticStruct1 { }
2719 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!()));
2721 static struct StaticStruct2 { int a, b; }
2722 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int)));
2724 int i;
2726 struct NestedStruct1 { void f() { ++i; } }
2727 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!()));
2729 struct NestedStruct2 { int a; void f() { ++i; } }
2730 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int));
2732 class NestedClass { int a; void f() { ++i; } }
2733 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int));
2735 static interface I {}
2736 static assert(is(Fields!I == AliasSeq!()));
2739 //Required for FieldNameTuple
2740 private enum NameOf(alias T) = T.stringof;
2743 * Get as an expression tuple the names of the fields of a struct, class, or
2744 * union. This consists of the fields that take up memory space, excluding the
2745 * hidden fields like the virtual function table pointer or a context pointer
2746 * for nested types.
2747 * Inherited fields (for classes) are not included.
2748 * If `T` isn't a struct, class, interface or union, an
2749 * expression tuple with an empty string is returned.
2751 * History:
2752 * - Returned `AliasSeq!""` for interfaces prior to 2.097
2754 template FieldNameTuple(T)
2756 import std.meta : staticMap;
2757 static if (is(T == struct) || is(T == union))
2758 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]);
2759 else static if (is(T == class) || is(T == interface))
2760 alias FieldNameTuple = staticMap!(NameOf, T.tupleof);
2761 else
2762 alias FieldNameTuple = AliasSeq!"";
2766 @safe unittest
2768 import std.meta : AliasSeq;
2769 struct S { int x; float y; }
2770 static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
2771 static assert(FieldNameTuple!int == AliasSeq!"");
2774 @safe unittest
2776 static assert(FieldNameTuple!int == AliasSeq!"");
2778 static struct StaticStruct1 { }
2779 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!()));
2781 static struct StaticStruct2 { int a, b; }
2782 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b"));
2784 static class StaticClass1 { }
2785 static assert(is(FieldNameTuple!StaticClass1 == AliasSeq!()));
2787 static class StaticClass2 : StaticClass1 { int a, b; }
2788 static assert(FieldNameTuple!StaticClass2 == AliasSeq!("a", "b"));
2790 static class StaticClass3 : StaticClass2 { int c; }
2791 static assert(FieldNameTuple!StaticClass3 == AliasSeq!("c"));
2793 int i;
2795 struct NestedStruct1 { void f() { ++i; } }
2796 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!()));
2798 struct NestedStruct2 { int a; void f() { ++i; } }
2799 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a");
2801 class NestedClass { int a; void f() { ++i; } }
2802 static assert(FieldNameTuple!NestedClass == AliasSeq!"a");
2804 interface I {}
2805 static assert(FieldNameTuple!I == AliasSeq!());
2809 /***
2810 Get the primitive types of the fields of a struct or class, in
2811 topological order.
2813 template RepresentationTypeTuple(T)
2815 static if (is(T == struct) || is(T == union) || is(T == class))
2817 alias RepresentationTypeTuple = staticMapMeta!(RepresentationTypeTupleImpl, FieldTypeTuple!T);
2819 else
2821 alias RepresentationTypeTuple = RepresentationTypeTupleImpl!T;
2826 @safe unittest
2828 struct S1 { int a; float b; }
2829 struct S2 { char[] a; union { S1 b; S1 * c; } }
2830 alias R = RepresentationTypeTuple!S2;
2831 assert(R.length == 4
2832 && is(R[0] == char[]) && is(R[1] == int)
2833 && is(R[2] == float) && is(R[3] == S1*));
2836 @safe unittest
2838 alias S1 = RepresentationTypeTuple!int;
2839 static assert(is(S1 == AliasSeq!int));
2841 struct S2 { int a; }
2842 struct S3 { int a; char b; }
2843 struct S4 { S1 a; int b; S3 c; }
2844 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int));
2845 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char)));
2846 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char)));
2848 struct S11 { int a; float b; }
2849 struct S21 { char[] a; union { S11 b; S11 * c; } }
2850 alias R = RepresentationTypeTuple!S21;
2851 assert(R.length == 4
2852 && is(R[0] == char[]) && is(R[1] == int)
2853 && is(R[2] == float) && is(R[3] == S11*));
2855 class C { int a; float b; }
2856 alias R1 = RepresentationTypeTuple!C;
2857 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float));
2859 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
2860 import std.typecons : Rebindable;
2862 struct S5 { int a; Rebindable!(immutable Object) b; }
2863 alias R2 = RepresentationTypeTuple!S5;
2864 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
2866 static assert(is(RepresentationTypeTuple!noreturn == AliasSeq!noreturn));
2869 @safe unittest
2871 struct VeryLargeType
2873 import std.format : format;
2874 import std.range : iota;
2876 static foreach (i; 500.iota)
2878 mixin(format!"int v%s;"(i));
2882 alias BigList = RepresentationTypeTuple!VeryLargeType;
2885 private template RepresentationTypeTupleImpl(T)
2887 import std.typecons : Rebindable;
2889 static if (is(immutable T == immutable Rebindable!R, R))
2891 alias RepresentationTypeTupleImpl
2892 = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R);
2894 else static if (is(T == struct) || is(T == union))
2896 // @@@BUG@@@ this should work
2897 //alias .RepresentationTypes!(T[0].tupleof)
2898 // RepresentationTypes;
2899 alias RepresentationTypeTupleImpl
2900 = staticMapMeta!(.RepresentationTypeTupleImpl, FieldTypeTuple!(T));
2902 else
2904 alias RepresentationTypeTupleImpl
2905 = AliasSeq!T;
2910 Statically evaluates to `true` if and only if `T`'s
2911 representation contains at least one field of pointer or array type.
2912 Members of class types are not considered raw pointers. Pointers to
2913 immutable objects are not considered raw aliasing.
2915 private template hasRawAliasing(T)
2917 enum hasRawAliasing = anySatisfy!(hasRawAliasingImpl, RepresentationTypeTuple!T);
2921 @safe unittest
2923 // simple types
2924 static assert(!hasRawAliasing!int);
2925 static assert( hasRawAliasing!(char*));
2926 // references aren't raw pointers
2927 static assert(!hasRawAliasing!Object);
2928 // built-in arrays do contain raw pointers
2929 static assert( hasRawAliasing!(int[]));
2930 // aggregate of simple types
2931 struct S1 { int a; double b; }
2932 static assert(!hasRawAliasing!S1);
2933 // indirect aggregation
2934 struct S2 { S1 a; double b; }
2935 static assert(!hasRawAliasing!S2);
2938 // https://issues.dlang.org/show_bug.cgi?id=19228
2939 @safe unittest
2941 static struct C
2943 int*[1] a;
2945 static assert(hasRawAliasing!C);
2948 @safe unittest
2950 // struct with a pointer member
2951 struct S3 { int a; double * b; }
2952 static assert( hasRawAliasing!S3);
2953 // struct with an indirect pointer member
2954 struct S4 { S3 a; double b; }
2955 static assert( hasRawAliasing!S4);
2956 struct S5 { int a; Object z; int c; }
2957 static assert( hasRawAliasing!S3);
2958 static assert( hasRawAliasing!S4);
2959 static assert(!hasRawAliasing!S5);
2961 union S6 { int a; int b; }
2962 union S7 { int a; int * b; }
2963 static assert(!hasRawAliasing!S6);
2964 static assert( hasRawAliasing!S7);
2966 static assert(!hasRawAliasing!(void delegate()));
2967 static assert(!hasRawAliasing!(void delegate() const));
2968 static assert(!hasRawAliasing!(void delegate() immutable));
2969 static assert(!hasRawAliasing!(void delegate() shared));
2970 static assert(!hasRawAliasing!(void delegate() shared const));
2971 static assert(!hasRawAliasing!(const(void delegate())));
2972 static assert(!hasRawAliasing!(immutable(void delegate())));
2974 struct S8 { void delegate() a; int b; Object c; }
2975 class S12 { typeof(S8.tupleof) a; }
2976 class S13 { typeof(S8.tupleof) a; int* b; }
2977 static assert(!hasRawAliasing!S8);
2978 static assert(!hasRawAliasing!S12);
2979 static assert( hasRawAliasing!S13);
2981 enum S9 { a }
2982 static assert(!hasRawAliasing!S9);
2984 // indirect members
2985 struct S10 { S7 a; int b; }
2986 struct S11 { S6 a; int b; }
2987 static assert( hasRawAliasing!S10);
2988 static assert(!hasRawAliasing!S11);
2990 static assert( hasRawAliasing!(int[string]));
2991 static assert(!hasRawAliasing!(immutable(int[string])));
2994 private template hasRawAliasingImpl(T)
2996 static if (is(T foo : U*, U) && !isFunctionPointer!T)
2997 enum hasRawAliasingImpl = !is(U == immutable);
2998 else static if (is(T foo : U[N], U, size_t N))
2999 // separate static ifs to avoid forward reference
3000 static if (is(U == class) || is(U == interface))
3001 enum hasRawAliasingImpl = false;
3002 else
3003 enum hasRawAliasingImpl = hasRawAliasingImpl!U;
3004 else static if (is(T foo : U[], U) && !isStaticArray!(T))
3005 enum hasRawAliasingImpl = !is(U == immutable);
3006 else static if (isAssociativeArray!(T))
3007 enum hasRawAliasingImpl = !is(T == immutable);
3008 else
3009 enum hasRawAliasingImpl = false;
3013 Statically evaluates to `true` if and only if `T`'s
3014 representation contains at least one non-shared field of pointer or
3015 array type. Members of class types are not considered raw pointers.
3016 Pointers to immutable objects are not considered raw aliasing.
3018 private template hasRawUnsharedAliasing(T)
3020 enum hasRawUnsharedAliasing = anySatisfy!(hasRawUnsharedAliasingImpl, RepresentationTypeTuple!T);
3024 @safe unittest
3026 // simple types
3027 static assert(!hasRawUnsharedAliasing!int);
3028 static assert( hasRawUnsharedAliasing!(char*));
3029 static assert(!hasRawUnsharedAliasing!(shared char*));
3030 // references aren't raw pointers
3031 static assert(!hasRawUnsharedAliasing!Object);
3032 // built-in arrays do contain raw pointers
3033 static assert( hasRawUnsharedAliasing!(int[]));
3034 static assert(!hasRawUnsharedAliasing!(shared int[]));
3035 // aggregate of simple types
3036 struct S1 { int a; double b; }
3037 static assert(!hasRawUnsharedAliasing!S1);
3038 // indirect aggregation
3039 struct S2 { S1 a; double b; }
3040 static assert(!hasRawUnsharedAliasing!S2);
3041 // struct with a pointer member
3042 struct S3 { int a; double * b; }
3043 static assert( hasRawUnsharedAliasing!S3);
3044 struct S4 { int a; shared double * b; }
3045 static assert(!hasRawUnsharedAliasing!S4);
3048 @safe unittest
3050 // struct with a pointer member
3051 struct S3 { int a; double * b; }
3052 static assert( hasRawUnsharedAliasing!S3);
3053 struct S4 { int a; shared double * b; }
3054 static assert(!hasRawUnsharedAliasing!S4);
3055 // struct with an indirect pointer member
3056 struct S5 { S3 a; double b; }
3057 static assert( hasRawUnsharedAliasing!S5);
3058 struct S6 { S4 a; double b; }
3059 static assert(!hasRawUnsharedAliasing!S6);
3060 struct S7 { int a; Object z; int c; }
3061 static assert( hasRawUnsharedAliasing!S5);
3062 static assert(!hasRawUnsharedAliasing!S6);
3063 static assert(!hasRawUnsharedAliasing!S7);
3065 union S8 { int a; int b; }
3066 union S9 { int a; int* b; }
3067 union S10 { int a; shared int* b; }
3068 static assert(!hasRawUnsharedAliasing!S8);
3069 static assert( hasRawUnsharedAliasing!S9);
3070 static assert(!hasRawUnsharedAliasing!S10);
3072 static assert(!hasRawUnsharedAliasing!(void delegate()));
3073 static assert(!hasRawUnsharedAliasing!(void delegate() const));
3074 static assert(!hasRawUnsharedAliasing!(void delegate() immutable));
3075 static assert(!hasRawUnsharedAliasing!(void delegate() shared));
3076 static assert(!hasRawUnsharedAliasing!(void delegate() shared const));
3077 static assert(!hasRawUnsharedAliasing!(const(void delegate())));
3078 static assert(!hasRawUnsharedAliasing!(const(void delegate() const)));
3079 static assert(!hasRawUnsharedAliasing!(const(void delegate() immutable)));
3080 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared)));
3081 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared const)));
3082 static assert(!hasRawUnsharedAliasing!(immutable(void delegate())));
3083 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() const)));
3084 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() immutable)));
3085 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared)));
3086 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared const)));
3087 static assert(!hasRawUnsharedAliasing!(shared(void delegate())));
3088 static assert(!hasRawUnsharedAliasing!(shared(void delegate() const)));
3089 static assert(!hasRawUnsharedAliasing!(shared(void delegate() immutable)));
3090 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared)));
3091 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared const)));
3092 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate()))));
3093 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() const))));
3094 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() immutable))));
3095 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared))));
3096 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared const))));
3097 static assert(!hasRawUnsharedAliasing!(void function()));
3099 enum S13 { a }
3100 static assert(!hasRawUnsharedAliasing!S13);
3102 // indirect members
3103 struct S14 { S9 a; int b; }
3104 struct S15 { S10 a; int b; }
3105 struct S16 { S6 a; int b; }
3106 static assert( hasRawUnsharedAliasing!S14);
3107 static assert(!hasRawUnsharedAliasing!S15);
3108 static assert(!hasRawUnsharedAliasing!S16);
3110 static assert( hasRawUnsharedAliasing!(int[string]));
3111 static assert(!hasRawUnsharedAliasing!(shared(int[string])));
3112 static assert(!hasRawUnsharedAliasing!(immutable(int[string])));
3114 struct S17
3116 void delegate() shared a;
3117 void delegate() immutable b;
3118 void delegate() shared const c;
3119 shared(void delegate()) d;
3120 shared(void delegate() shared) e;
3121 shared(void delegate() immutable) f;
3122 shared(void delegate() shared const) g;
3123 immutable(void delegate()) h;
3124 immutable(void delegate() shared) i;
3125 immutable(void delegate() immutable) j;
3126 immutable(void delegate() shared const) k;
3127 shared(const(void delegate())) l;
3128 shared(const(void delegate() shared)) m;
3129 shared(const(void delegate() immutable)) n;
3130 shared(const(void delegate() shared const)) o;
3132 struct S18 { typeof(S17.tupleof) a; void delegate() p; }
3133 struct S19 { typeof(S17.tupleof) a; Object p; }
3134 struct S20 { typeof(S17.tupleof) a; int* p; }
3135 class S21 { typeof(S17.tupleof) a; }
3136 class S22 { typeof(S17.tupleof) a; void delegate() p; }
3137 class S23 { typeof(S17.tupleof) a; Object p; }
3138 class S24 { typeof(S17.tupleof) a; int* p; }
3139 static assert(!hasRawUnsharedAliasing!S17);
3140 static assert(!hasRawUnsharedAliasing!(immutable(S17)));
3141 static assert(!hasRawUnsharedAliasing!(shared(S17)));
3142 static assert(!hasRawUnsharedAliasing!S18);
3143 static assert(!hasRawUnsharedAliasing!(immutable(S18)));
3144 static assert(!hasRawUnsharedAliasing!(shared(S18)));
3145 static assert(!hasRawUnsharedAliasing!S19);
3146 static assert(!hasRawUnsharedAliasing!(immutable(S19)));
3147 static assert(!hasRawUnsharedAliasing!(shared(S19)));
3148 static assert( hasRawUnsharedAliasing!S20);
3149 static assert(!hasRawUnsharedAliasing!(immutable(S20)));
3150 static assert(!hasRawUnsharedAliasing!(shared(S20)));
3151 static assert(!hasRawUnsharedAliasing!S21);
3152 static assert(!hasRawUnsharedAliasing!(immutable(S21)));
3153 static assert(!hasRawUnsharedAliasing!(shared(S21)));
3154 static assert(!hasRawUnsharedAliasing!S22);
3155 static assert(!hasRawUnsharedAliasing!(immutable(S22)));
3156 static assert(!hasRawUnsharedAliasing!(shared(S22)));
3157 static assert(!hasRawUnsharedAliasing!S23);
3158 static assert(!hasRawUnsharedAliasing!(immutable(S23)));
3159 static assert(!hasRawUnsharedAliasing!(shared(S23)));
3160 static assert( hasRawUnsharedAliasing!S24);
3161 static assert(!hasRawUnsharedAliasing!(immutable(S24)));
3162 static assert(!hasRawUnsharedAliasing!(shared(S24)));
3163 struct S25 {}
3164 class S26 {}
3165 interface S27 {}
3166 union S28 {}
3167 static assert(!hasRawUnsharedAliasing!S25);
3168 static assert(!hasRawUnsharedAliasing!S26);
3169 static assert(!hasRawUnsharedAliasing!S27);
3170 static assert(!hasRawUnsharedAliasing!S28);
3173 private template hasRawUnsharedAliasingImpl(T)
3175 static if (is(T foo : U*, U) && !isFunctionPointer!T)
3176 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3177 else static if (is(T foo : U[], U) && !isStaticArray!T)
3178 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3179 else static if (isAssociativeArray!T)
3180 enum hasRawUnsharedAliasingImpl = !is(T == immutable) && !is(T == shared);
3181 else
3182 enum hasRawUnsharedAliasingImpl = false;
3186 Statically evaluates to `true` if and only if `T`'s
3187 representation includes at least one non-immutable object reference.
3190 private template hasObjects(T)
3192 static if (is(T == struct))
3194 enum hasObjects = anySatisfy!(.hasObjects, RepresentationTypeTuple!T);
3196 else
3198 enum hasObjects = (is(T == class) || is(T == interface)) && !is(T == immutable);
3203 Statically evaluates to `true` if and only if `T`'s
3204 representation includes at least one non-immutable non-shared object
3205 reference.
3207 private template hasUnsharedObjects(T)
3209 static if (is(T == struct))
3211 enum hasUnsharedObjects = anySatisfy!(.hasUnsharedObjects, RepresentationTypeTuple!T);
3213 else
3215 enum hasUnsharedObjects = (is(T == class) || is(T == interface)) &&
3216 !is(T == immutable) && !is(T == shared);
3221 Returns `true` if and only if `T`'s representation includes at
3222 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3223 is not immutable;) $(LI an array `U[]` and `U` is not
3224 immutable;) $(LI a reference to a class or interface type `C` and `C` is
3225 not immutable.) $(LI an associative array that is not immutable.)
3226 $(LI a delegate.))
3228 template hasAliasing(T...)
3230 enum hasAliasing = anySatisfy!(hasAliasingImpl, T);
3234 @safe unittest
3236 struct S1 { int a; Object b; }
3237 struct S2 { string a; }
3238 struct S3 { int a; immutable Object b; }
3239 struct S4 { float[3] vals; }
3240 static assert( hasAliasing!S1);
3241 static assert(!hasAliasing!S2);
3242 static assert(!hasAliasing!S3);
3243 static assert(!hasAliasing!S4);
3246 @safe unittest
3248 static assert( hasAliasing!(uint[uint]));
3249 static assert(!hasAliasing!(immutable(uint[uint])));
3250 static assert( hasAliasing!(void delegate()));
3251 static assert( hasAliasing!(void delegate() const));
3252 static assert(!hasAliasing!(void delegate() immutable));
3253 static assert( hasAliasing!(void delegate() shared));
3254 static assert( hasAliasing!(void delegate() shared const));
3255 static assert( hasAliasing!(const(void delegate())));
3256 static assert( hasAliasing!(const(void delegate() const)));
3257 static assert(!hasAliasing!(const(void delegate() immutable)));
3258 static assert( hasAliasing!(const(void delegate() shared)));
3259 static assert( hasAliasing!(const(void delegate() shared const)));
3260 static assert(!hasAliasing!(immutable(void delegate())));
3261 static assert(!hasAliasing!(immutable(void delegate() const)));
3262 static assert(!hasAliasing!(immutable(void delegate() immutable)));
3263 static assert(!hasAliasing!(immutable(void delegate() shared)));
3264 static assert(!hasAliasing!(immutable(void delegate() shared const)));
3265 static assert( hasAliasing!(shared(const(void delegate()))));
3266 static assert( hasAliasing!(shared(const(void delegate() const))));
3267 static assert(!hasAliasing!(shared(const(void delegate() immutable))));
3268 static assert( hasAliasing!(shared(const(void delegate() shared))));
3269 static assert( hasAliasing!(shared(const(void delegate() shared const))));
3270 static assert(!hasAliasing!(void function()));
3272 interface I;
3273 static assert( hasAliasing!I);
3275 import std.typecons : Rebindable;
3276 static assert( hasAliasing!(Rebindable!(const Object)));
3277 static assert(!hasAliasing!(Rebindable!(immutable Object)));
3278 static assert( hasAliasing!(Rebindable!(shared Object)));
3279 static assert( hasAliasing!(Rebindable!Object));
3281 struct S5
3283 void delegate() immutable b;
3284 shared(void delegate() immutable) f;
3285 immutable(void delegate() immutable) j;
3286 shared(const(void delegate() immutable)) n;
3288 struct S6 { typeof(S5.tupleof) a; void delegate() p; }
3289 static assert(!hasAliasing!S5);
3290 static assert( hasAliasing!S6);
3292 struct S7 { void delegate() a; int b; Object c; }
3293 class S8 { int a; int b; }
3294 class S9 { typeof(S8.tupleof) a; }
3295 class S10 { typeof(S8.tupleof) a; int* b; }
3296 static assert( hasAliasing!S7);
3297 static assert( hasAliasing!S8);
3298 static assert( hasAliasing!S9);
3299 static assert( hasAliasing!S10);
3300 struct S11 {}
3301 class S12 {}
3302 interface S13 {}
3303 union S14 {}
3304 static assert(!hasAliasing!S11);
3305 static assert( hasAliasing!S12);
3306 static assert( hasAliasing!S13);
3307 static assert(!hasAliasing!S14);
3309 class S15 { S15[1] a; }
3310 static assert( hasAliasing!S15);
3311 static assert(!hasAliasing!(immutable(S15)));
3313 static assert(!hasAliasing!noreturn);
3316 private template hasAliasingImpl(T)
3318 import std.typecons : Rebindable;
3320 static if (is(immutable T == immutable Rebindable!R, R))
3322 enum hasAliasingImpl = hasAliasingImpl!R;
3324 else
3326 template isAliasingDelegate(T)
3328 enum isAliasingDelegate = isDelegate!T
3329 && !is(T == immutable)
3330 && !is(FunctionTypeOf!T == immutable);
3332 enum hasAliasingImpl = hasRawAliasing!T || hasObjects!T ||
3333 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T);
3338 Returns `true` if and only if `T`'s representation includes at
3339 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an
3340 array `U[]`;) $(LI a reference to a class type `C`;)
3341 $(LI an associative array;) $(LI a delegate;)
3342 $(LI a [context pointer][isNested].))
3344 template hasIndirections(T)
3346 import core.internal.traits : _hasIndirections = hasIndirections;
3347 alias hasIndirections = _hasIndirections!T;
3351 @safe unittest
3353 static assert( hasIndirections!(int[string]));
3354 static assert( hasIndirections!(void delegate()));
3355 static assert( hasIndirections!(void delegate() immutable));
3356 static assert( hasIndirections!(immutable(void delegate())));
3357 static assert( hasIndirections!(immutable(void delegate() immutable)));
3359 static assert(!hasIndirections!(void function()));
3360 static assert( hasIndirections!(void*[1]));
3361 static assert(!hasIndirections!(byte[1]));
3364 @safe unittest
3366 // void static array hides actual type of bits, so "may have indirections".
3367 static assert( hasIndirections!(void[1]));
3368 interface I {}
3369 struct S1 {}
3370 struct S2 { int a; }
3371 struct S3 { int a; int b; }
3372 struct S4 { int a; int* b; }
3373 struct S5 { int a; Object b; }
3374 struct S6 { int a; string b; }
3375 struct S7 { int a; immutable Object b; }
3376 struct S8 { int a; immutable I b; }
3377 struct S9 { int a; void delegate() b; }
3378 struct S10 { int a; immutable(void delegate()) b; }
3379 struct S11 { int a; void delegate() immutable b; }
3380 struct S12 { int a; immutable(void delegate() immutable) b; }
3381 class S13 {}
3382 class S14 { int a; }
3383 class S15 { int a; int b; }
3384 class S16 { int a; Object b; }
3385 class S17 { string a; }
3386 class S18 { int a; immutable Object b; }
3387 class S19 { int a; immutable(void delegate() immutable) b; }
3388 union S20 {}
3389 union S21 { int a; }
3390 union S22 { int a; int b; }
3391 union S23 { int a; Object b; }
3392 union S24 { string a; }
3393 union S25 { int a; immutable Object b; }
3394 union S26 { int a; immutable(void delegate() immutable) b; }
3395 static assert( hasIndirections!I);
3396 static assert(!hasIndirections!S1);
3397 static assert(!hasIndirections!S2);
3398 static assert(!hasIndirections!S3);
3399 static assert( hasIndirections!S4);
3400 static assert( hasIndirections!S5);
3401 static assert( hasIndirections!S6);
3402 static assert( hasIndirections!S7);
3403 static assert( hasIndirections!S8);
3404 static assert( hasIndirections!S9);
3405 static assert( hasIndirections!S10);
3406 static assert( hasIndirections!S12);
3407 static assert( hasIndirections!S13);
3408 static assert( hasIndirections!S14);
3409 static assert( hasIndirections!S15);
3410 static assert( hasIndirections!S16);
3411 static assert( hasIndirections!S17);
3412 static assert( hasIndirections!S18);
3413 static assert( hasIndirections!S19);
3414 static assert(!hasIndirections!S20);
3415 static assert(!hasIndirections!S21);
3416 static assert(!hasIndirections!S22);
3417 static assert( hasIndirections!S23);
3418 static assert( hasIndirections!S24);
3419 static assert( hasIndirections!S25);
3420 static assert( hasIndirections!S26);
3421 int local;
3422 struct HasContextPointer { int opCall() { return ++local; } }
3423 static assert(hasIndirections!HasContextPointer);
3425 static assert(!hasIndirections!noreturn);
3428 // https://issues.dlang.org/show_bug.cgi?id=12000
3429 @safe unittest
3431 static struct S(T)
3433 static assert(hasIndirections!T);
3436 static class A(T)
3438 S!A a;
3441 A!int dummy;
3445 Returns `true` if and only if `T`'s representation includes at
3446 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3447 is not immutable or shared;) $(LI an array `U[]` and `U` is not
3448 immutable or shared;) $(LI a reference to a class type `C` and
3449 `C` is not immutable or shared.) $(LI an associative array that is not
3450 immutable or shared.) $(LI a delegate that is not shared.))
3453 template hasUnsharedAliasing(T...)
3455 enum hasUnsharedAliasing = anySatisfy!(hasUnsharedAliasingImpl, T);
3459 @safe unittest
3461 struct S1 { int a; Object b; }
3462 struct S2 { string a; }
3463 struct S3 { int a; immutable Object b; }
3464 static assert( hasUnsharedAliasing!S1);
3465 static assert(!hasUnsharedAliasing!S2);
3466 static assert(!hasUnsharedAliasing!S3);
3468 struct S4 { int a; shared Object b; }
3469 struct S5 { char[] a; }
3470 struct S6 { shared char[] b; }
3471 struct S7 { float[3] vals; }
3472 static assert(!hasUnsharedAliasing!S4);
3473 static assert( hasUnsharedAliasing!S5);
3474 static assert(!hasUnsharedAliasing!S6);
3475 static assert(!hasUnsharedAliasing!S7);
3478 @safe unittest
3480 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
3481 import std.typecons : Rebindable;
3482 struct S8 { int a; Rebindable!(immutable Object) b; }
3483 static assert(!hasUnsharedAliasing!S8);
3485 static assert( hasUnsharedAliasing!(uint[uint]));
3487 static assert( hasUnsharedAliasing!(void delegate()));
3488 static assert( hasUnsharedAliasing!(void delegate() const));
3489 static assert(!hasUnsharedAliasing!(void delegate() immutable));
3490 static assert(!hasUnsharedAliasing!(void delegate() shared));
3491 static assert(!hasUnsharedAliasing!(void delegate() shared const));
3494 @safe unittest
3496 import std.typecons : Rebindable;
3497 static assert( hasUnsharedAliasing!(const(void delegate())));
3498 static assert( hasUnsharedAliasing!(const(void delegate() const)));
3499 static assert(!hasUnsharedAliasing!(const(void delegate() immutable)));
3500 static assert(!hasUnsharedAliasing!(const(void delegate() shared)));
3501 static assert(!hasUnsharedAliasing!(const(void delegate() shared const)));
3502 static assert(!hasUnsharedAliasing!(immutable(void delegate())));
3503 static assert(!hasUnsharedAliasing!(immutable(void delegate() const)));
3504 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable)));
3505 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared)));
3506 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const)));
3507 static assert(!hasUnsharedAliasing!(shared(void delegate())));
3508 static assert(!hasUnsharedAliasing!(shared(void delegate() const)));
3509 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable)));
3510 static assert(!hasUnsharedAliasing!(shared(void delegate() shared)));
3511 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const)));
3512 static assert(!hasUnsharedAliasing!(shared(const(void delegate()))));
3513 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const))));
3514 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable))));
3515 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared))));
3516 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const))));
3517 static assert(!hasUnsharedAliasing!(void function()));
3519 interface I {}
3520 static assert(hasUnsharedAliasing!I);
3522 static assert( hasUnsharedAliasing!(Rebindable!(const Object)));
3523 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object)));
3524 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object)));
3525 static assert( hasUnsharedAliasing!(Rebindable!Object));
3527 /* https://issues.dlang.org/show_bug.cgi?id=6979 */
3528 static assert(!hasUnsharedAliasing!(int, shared(int)*));
3529 static assert( hasUnsharedAliasing!(int, int*));
3530 static assert( hasUnsharedAliasing!(int, const(int)[]));
3531 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object));
3532 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object)));
3533 static assert(!hasUnsharedAliasing!());
3535 struct S9
3537 void delegate() shared a;
3538 void delegate() immutable b;
3539 void delegate() shared const c;
3540 shared(void delegate()) d;
3541 shared(void delegate() shared) e;
3542 shared(void delegate() immutable) f;
3543 shared(void delegate() shared const) g;
3544 immutable(void delegate()) h;
3545 immutable(void delegate() shared) i;
3546 immutable(void delegate() immutable) j;
3547 immutable(void delegate() shared const) k;
3548 shared(const(void delegate())) l;
3549 shared(const(void delegate() shared)) m;
3550 shared(const(void delegate() immutable)) n;
3551 shared(const(void delegate() shared const)) o;
3553 struct S10 { typeof(S9.tupleof) a; void delegate() p; }
3554 struct S11 { typeof(S9.tupleof) a; Object p; }
3555 struct S12 { typeof(S9.tupleof) a; int* p; }
3556 class S13 { typeof(S9.tupleof) a; }
3557 class S14 { typeof(S9.tupleof) a; void delegate() p; }
3558 class S15 { typeof(S9.tupleof) a; Object p; }
3559 class S16 { typeof(S9.tupleof) a; int* p; }
3560 static assert(!hasUnsharedAliasing!S9);
3561 static assert(!hasUnsharedAliasing!(immutable(S9)));
3562 static assert(!hasUnsharedAliasing!(shared(S9)));
3563 static assert( hasUnsharedAliasing!S10);
3564 static assert(!hasUnsharedAliasing!(immutable(S10)));
3565 static assert(!hasUnsharedAliasing!(shared(S10)));
3566 static assert( hasUnsharedAliasing!S11);
3567 static assert(!hasUnsharedAliasing!(immutable(S11)));
3568 static assert(!hasUnsharedAliasing!(shared(S11)));
3569 static assert( hasUnsharedAliasing!S12);
3570 static assert(!hasUnsharedAliasing!(immutable(S12)));
3571 static assert(!hasUnsharedAliasing!(shared(S12)));
3572 static assert( hasUnsharedAliasing!S13);
3573 static assert(!hasUnsharedAliasing!(immutable(S13)));
3574 static assert(!hasUnsharedAliasing!(shared(S13)));
3575 static assert( hasUnsharedAliasing!S14);
3576 static assert(!hasUnsharedAliasing!(immutable(S14)));
3577 static assert(!hasUnsharedAliasing!(shared(S14)));
3578 static assert( hasUnsharedAliasing!S15);
3579 static assert(!hasUnsharedAliasing!(immutable(S15)));
3580 static assert(!hasUnsharedAliasing!(shared(S15)));
3581 static assert( hasUnsharedAliasing!S16);
3582 static assert(!hasUnsharedAliasing!(immutable(S16)));
3583 static assert(!hasUnsharedAliasing!(shared(S16)));
3584 struct S17 {}
3585 class S18 {}
3586 interface S19 {}
3587 union S20 {}
3588 static assert(!hasUnsharedAliasing!S17);
3589 static assert( hasUnsharedAliasing!S18);
3590 static assert( hasUnsharedAliasing!S19);
3591 static assert(!hasUnsharedAliasing!S20);
3593 static assert(!hasUnsharedAliasing!noreturn);
3596 private template hasUnsharedAliasingImpl(T)
3598 import std.typecons : Rebindable;
3600 static if (is(immutable T == immutable Rebindable!R, R))
3602 enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R;
3604 else
3606 template unsharedDelegate(T)
3608 enum bool unsharedDelegate = isDelegate!T
3609 && !is(T == shared)
3610 && !is(T == immutable)
3611 && !is(FunctionTypeOf!T == shared)
3612 && !is(FunctionTypeOf!T == immutable);
3615 enum hasUnsharedAliasingImpl =
3616 hasRawUnsharedAliasing!T ||
3617 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!T) ||
3618 hasUnsharedObjects!T;
3622 version (StdDdoc)
3625 True if `S` or any type embedded directly in the representation of `S`
3626 defines an elaborate copy constructor. Elaborate copy constructors are
3627 introduced by defining `this(this)` for a `struct`.
3629 Classes and unions never have elaborate copy constructors.
3631 template hasElaborateCopyConstructor(S)
3633 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3634 alias hasElaborateCopyConstructor = hasElabCCtor!(S);
3637 else
3639 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3640 alias hasElaborateCopyConstructor = hasElabCCtor;
3644 @safe unittest
3646 static assert(!hasElaborateCopyConstructor!int);
3648 static struct S1 { }
3649 static struct S2 { this(this) {} }
3650 static struct S3 { S2 field; }
3651 static struct S4 { S3[1] field; }
3652 static struct S5 { S3[] field; }
3653 static struct S6 { S3[0] field; }
3654 static struct S7 { @disable this(); S3 field; }
3655 static assert(!hasElaborateCopyConstructor!S1);
3656 static assert( hasElaborateCopyConstructor!S2);
3657 static assert( hasElaborateCopyConstructor!(immutable S2));
3658 static assert( hasElaborateCopyConstructor!S3);
3659 static assert( hasElaborateCopyConstructor!(S3[1]));
3660 static assert(!hasElaborateCopyConstructor!(S3[0]));
3661 static assert( hasElaborateCopyConstructor!S4);
3662 static assert(!hasElaborateCopyConstructor!S5);
3663 static assert(!hasElaborateCopyConstructor!S6);
3664 static assert( hasElaborateCopyConstructor!S7);
3668 True if `S` or any type directly embedded in the representation of `S`
3669 defines an elaborate assignment. Elaborate assignments are introduced by
3670 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this)))
3671 for a `struct` or when there is a compiler-generated `opAssign`.
3673 A type `S` gets compiler-generated `opAssign` if it has
3674 an elaborate destructor.
3676 Classes and unions never have elaborate assignments.
3678 Note: Structs with (possibly nested) postblit operator(s) will have a
3679 hidden yet elaborate compiler generated assignment operator (unless
3680 explicitly disabled).
3682 template hasElaborateAssign(S)
3684 static if (isStaticArray!S && S.length)
3686 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0]));
3688 else static if (is(S == struct))
3690 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
3691 is(typeof(S.init.opAssign(lvalueOf!S))) ||
3692 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S);
3694 else
3696 enum bool hasElaborateAssign = false;
3701 @safe unittest
3703 static assert(!hasElaborateAssign!int);
3705 static struct S { void opAssign(S) {} }
3706 static assert( hasElaborateAssign!S);
3707 static assert(!hasElaborateAssign!(const(S)));
3709 static struct S1 { void opAssign(ref S1) {} }
3710 static struct S2 { void opAssign(int) {} }
3711 static struct S3 { S s; }
3712 static assert( hasElaborateAssign!S1);
3713 static assert(!hasElaborateAssign!S2);
3714 static assert( hasElaborateAssign!S3);
3715 static assert( hasElaborateAssign!(S3[1]));
3716 static assert(!hasElaborateAssign!(S3[0]));
3719 @safe unittest
3721 static struct S { void opAssign(S) {} }
3722 static struct S4
3724 void opAssign(U)(U u) {}
3725 @disable void opAssign(U)(ref U u);
3727 static assert( hasElaborateAssign!S4);
3729 static struct S41
3731 void opAssign(U)(ref U u) {}
3732 @disable void opAssign(U)(U u);
3734 static assert( hasElaborateAssign!S41);
3736 static struct S5 { @disable this(); this(int n){ s = S(); } S s; }
3737 static assert( hasElaborateAssign!S5);
3739 static struct S6 { this(this) {} }
3740 static struct S7 { this(this) {} @disable void opAssign(S7); }
3741 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} }
3742 static struct S9 { this(this) {} void opAssign(int) {} }
3743 static struct S10 { ~this() { } }
3744 static assert( hasElaborateAssign!S6);
3745 static assert(!hasElaborateAssign!S7);
3746 static assert(!hasElaborateAssign!S8);
3747 static assert( hasElaborateAssign!S9);
3748 static assert( hasElaborateAssign!S10);
3749 static struct SS6 { S6 s; }
3750 static struct SS7 { S7 s; }
3751 static struct SS8 { S8 s; }
3752 static struct SS9 { S9 s; }
3753 static assert( hasElaborateAssign!SS6);
3754 static assert(!hasElaborateAssign!SS7);
3755 static assert(!hasElaborateAssign!SS8);
3756 static assert( hasElaborateAssign!SS9);
3759 version (StdDdoc)
3762 True if `S` or any type directly embedded in the representation
3763 of `S` defines an elaborate destructor. Elaborate destructors
3764 are introduced by defining `~this()` for a $(D
3765 struct).
3767 Classes and unions never have elaborate destructors, even
3768 though classes may define `~this()`.
3770 template hasElaborateDestructor(S)
3772 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3773 alias hasElaborateDestructor = hasElabDest!(S);
3776 else
3778 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3779 alias hasElaborateDestructor = hasElabDest;
3783 @safe unittest
3785 static assert(!hasElaborateDestructor!int);
3787 static struct S1 { }
3788 static struct S2 { ~this() {} }
3789 static struct S3 { S2 field; }
3790 static struct S4 { S3[1] field; }
3791 static struct S5 { S3[] field; }
3792 static struct S6 { S3[0] field; }
3793 static struct S7 { @disable this(); S3 field; }
3794 static assert(!hasElaborateDestructor!S1);
3795 static assert( hasElaborateDestructor!S2);
3796 static assert( hasElaborateDestructor!(immutable S2));
3797 static assert( hasElaborateDestructor!S3);
3798 static assert( hasElaborateDestructor!(S3[1]));
3799 static assert(!hasElaborateDestructor!(S3[0]));
3800 static assert( hasElaborateDestructor!S4);
3801 static assert(!hasElaborateDestructor!S5);
3802 static assert(!hasElaborateDestructor!S6);
3803 static assert( hasElaborateDestructor!S7);
3806 version (StdDdoc)
3809 True if `S` or any type embedded directly in the representation of `S`
3810 defines elaborate move semantics. Elaborate move semantics are
3811 introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
3813 Classes and unions never have elaborate move semantics.
3815 template hasElaborateMove(S)
3817 import core.internal.traits : hasElabMove = hasElaborateMove;
3818 alias hasElaborateMove = hasElabMove!(S);
3821 else
3823 import core.internal.traits : hasElabMove = hasElaborateMove;
3824 alias hasElaborateMove = hasElabMove;
3828 @safe unittest
3830 static assert(!hasElaborateMove!int);
3832 static struct S1 { }
3833 static struct S2 { void opPostMove(ref S2) {} }
3834 static struct S3 { void opPostMove(inout ref S3) inout {} }
3835 static struct S4 { void opPostMove(const ref S4) {} }
3836 static struct S5 { void opPostMove(S5) {} }
3837 static struct S6 { void opPostMove(int) {} }
3838 static struct S7 { S3[1] field; }
3839 static struct S8 { S3[] field; }
3840 static struct S9 { S3[0] field; }
3841 static struct S10 { @disable this(); S3 field; }
3842 static assert(!hasElaborateMove!S1);
3843 static assert( hasElaborateMove!S2);
3844 static assert( hasElaborateMove!S3);
3845 static assert( hasElaborateMove!(immutable S3));
3846 static assert( hasElaborateMove!S4);
3847 static assert(!hasElaborateMove!S5);
3848 static assert(!hasElaborateMove!S6);
3849 static assert( hasElaborateMove!S7);
3850 static assert(!hasElaborateMove!S8);
3851 static assert(!hasElaborateMove!S9);
3852 static assert( hasElaborateMove!S10);
3855 package alias Identity(alias A) = A;
3858 Yields `true` if and only if `T` is an aggregate that defines
3859 a symbol called `name`.
3861 enum hasMember(T, string name) = __traits(hasMember, T, name);
3864 @safe unittest
3866 static assert(!hasMember!(int, "blah"));
3867 struct S1 { int blah; }
3868 struct S2 { int blah(){ return 0; } }
3869 class C1 { int blah; }
3870 class C2 { int blah(){ return 0; } }
3871 static assert(hasMember!(S1, "blah"));
3872 static assert(hasMember!(S2, "blah"));
3873 static assert(hasMember!(C1, "blah"));
3874 static assert(hasMember!(C2, "blah"));
3877 @safe unittest
3879 // https://issues.dlang.org/show_bug.cgi?id=8321
3880 struct S {
3881 int x;
3882 void f(){}
3883 void t()(){}
3884 template T(){}
3886 struct R1(T) {
3887 T t;
3888 alias t this;
3890 struct R2(T) {
3891 T t;
3892 @property ref inout(T) payload() inout { return t; }
3893 alias t this;
3895 static assert(hasMember!(S, "x"));
3896 static assert(hasMember!(S, "f"));
3897 static assert(hasMember!(S, "t"));
3898 static assert(hasMember!(S, "T"));
3899 static assert(hasMember!(R1!S, "x"));
3900 static assert(hasMember!(R1!S, "f"));
3901 static assert(hasMember!(R1!S, "t"));
3902 static assert(hasMember!(R1!S, "T"));
3903 static assert(hasMember!(R2!S, "x"));
3904 static assert(hasMember!(R2!S, "f"));
3905 static assert(hasMember!(R2!S, "t"));
3906 static assert(hasMember!(R2!S, "T"));
3909 @safe unittest
3911 static struct S
3913 void opDispatch(string n, A)(A dummy) {}
3915 static assert(hasMember!(S, "foo"));
3919 * Whether the symbol represented by the string, member, exists and is a static member of T.
3921 * Params:
3922 * T = Type containing symbol `member`.
3923 * member = Name of symbol to test that resides in `T`.
3925 * Returns:
3926 * `true` iff `member` exists and is static.
3928 template hasStaticMember(T, string member)
3930 static if (__traits(hasMember, T, member))
3932 static if (is(T == V*, V))
3933 alias U = V;
3934 else
3935 alias U = T;
3937 import std.meta : Alias;
3938 alias sym = Alias!(__traits(getMember, U, member));
3940 static if (__traits(getOverloads, U, member).length == 0)
3941 enum bool hasStaticMember = __traits(compiles, &sym);
3942 else
3943 enum bool hasStaticMember = __traits(isStaticFunction, sym);
3945 else
3947 enum bool hasStaticMember = false;
3952 @safe unittest
3954 static struct S
3956 static void sf() {}
3957 void f() {}
3959 static int si;
3960 int i;
3963 static assert( hasStaticMember!(S, "sf"));
3964 static assert(!hasStaticMember!(S, "f"));
3966 static assert( hasStaticMember!(S, "si"));
3967 static assert(!hasStaticMember!(S, "i"));
3969 static assert(!hasStaticMember!(S, "hello"));
3972 @safe unittest
3974 static struct S
3976 enum X = 10;
3977 enum Y
3979 i = 10
3981 struct S {}
3982 class C {}
3984 static int sx = 0;
3985 __gshared int gx = 0;
3987 Y y;
3988 static Y sy;
3990 static void f();
3991 static void f2() pure nothrow @nogc @safe;
3993 void g() shared;
3995 static void function() fp;
3996 __gshared void function() gfp;
3997 void function() fpm;
3999 void delegate() dm;
4000 static void delegate() sd;
4002 void m();
4003 void m2() const pure nothrow @nogc @safe;
4005 inout(int) iom() inout;
4006 static inout(int) iosf(inout int x);
4008 @property int p();
4009 static @property int sp();
4012 static class C
4014 enum X = 10;
4015 enum Y
4017 i = 10
4019 struct S {}
4020 class C {}
4022 static int sx = 0;
4023 __gshared int gx = 0;
4025 Y y;
4026 static Y sy;
4028 static void f();
4029 static void f2() pure nothrow @nogc @safe;
4031 void g() shared { }
4033 static void function() fp;
4034 __gshared void function() gfp;
4035 void function() fpm;
4037 void delegate() dm;
4038 static void delegate() sd;
4040 void m() {}
4041 final void m2() const pure nothrow @nogc @safe;
4043 inout(int) iom() inout { return 10; }
4044 static inout(int) iosf(inout int x);
4046 @property int p() { return 10; }
4047 static @property int sp();
4050 static assert(!hasStaticMember!(S, "na"));
4051 static assert(!hasStaticMember!(S, "X"));
4052 static assert(!hasStaticMember!(S, "Y"));
4053 static assert(!hasStaticMember!(S, "Y.i"));
4054 static assert(!hasStaticMember!(S, "S"));
4055 static assert(!hasStaticMember!(S, "C"));
4056 static assert( hasStaticMember!(S, "sx"));
4057 static assert( hasStaticMember!(S, "gx"));
4058 static assert(!hasStaticMember!(S, "y"));
4059 static assert( hasStaticMember!(S, "sy"));
4060 static assert( hasStaticMember!(S, "f"));
4061 static assert( hasStaticMember!(S, "f2"));
4062 static assert(!hasStaticMember!(S, "dm"));
4063 static assert( hasStaticMember!(S, "sd"));
4064 static assert(!hasStaticMember!(S, "g"));
4065 static assert( hasStaticMember!(S, "fp"));
4066 static assert( hasStaticMember!(S, "gfp"));
4067 static assert(!hasStaticMember!(S, "fpm"));
4068 static assert(!hasStaticMember!(S, "m"));
4069 static assert(!hasStaticMember!(S, "m2"));
4070 static assert(!hasStaticMember!(S, "iom"));
4071 static assert( hasStaticMember!(S, "iosf"));
4072 static assert(!hasStaticMember!(S, "p"));
4073 static assert( hasStaticMember!(S, "sp"));
4075 static assert(!hasStaticMember!(C, "na"));
4076 static assert(!hasStaticMember!(C, "X"));
4077 static assert(!hasStaticMember!(C, "Y"));
4078 static assert(!hasStaticMember!(C, "Y.i"));
4079 static assert(!hasStaticMember!(C, "S"));
4080 static assert(!hasStaticMember!(C, "C"));
4081 static assert( hasStaticMember!(C, "sx"));
4082 static assert( hasStaticMember!(C, "gx"));
4083 static assert(!hasStaticMember!(C, "y"));
4084 static assert( hasStaticMember!(C, "sy"));
4085 static assert( hasStaticMember!(C, "f"));
4086 static assert( hasStaticMember!(C, "f2"));
4087 static assert(!hasStaticMember!(C, "dm"));
4088 static assert( hasStaticMember!(C, "sd"));
4089 static assert(!hasStaticMember!(C, "g"));
4090 static assert( hasStaticMember!(C, "fp"));
4091 static assert( hasStaticMember!(C, "gfp"));
4092 static assert(!hasStaticMember!(C, "fpm"));
4093 static assert(!hasStaticMember!(C, "m"));
4094 static assert(!hasStaticMember!(C, "m2"));
4095 static assert(!hasStaticMember!(C, "iom"));
4096 static assert( hasStaticMember!(C, "iosf"));
4097 static assert(!hasStaticMember!(C, "p"));
4098 static assert( hasStaticMember!(C, "sp"));
4100 alias P = S*;
4101 static assert(!hasStaticMember!(P, "na"));
4102 static assert(!hasStaticMember!(P, "X"));
4103 static assert(!hasStaticMember!(P, "Y"));
4104 static assert(!hasStaticMember!(P, "Y.i"));
4105 static assert(!hasStaticMember!(P, "S"));
4106 static assert(!hasStaticMember!(P, "C"));
4107 static assert( hasStaticMember!(P, "sx"));
4108 static assert( hasStaticMember!(P, "gx"));
4109 static assert(!hasStaticMember!(P, "y"));
4110 static assert( hasStaticMember!(P, "sy"));
4111 static assert( hasStaticMember!(P, "f"));
4112 static assert( hasStaticMember!(P, "f2"));
4113 static assert(!hasStaticMember!(P, "dm"));
4114 static assert( hasStaticMember!(P, "sd"));
4115 static assert(!hasStaticMember!(P, "g"));
4116 static assert( hasStaticMember!(P, "fp"));
4117 static assert( hasStaticMember!(P, "gfp"));
4118 static assert(!hasStaticMember!(P, "fpm"));
4119 static assert(!hasStaticMember!(P, "m"));
4120 static assert(!hasStaticMember!(P, "m2"));
4121 static assert(!hasStaticMember!(P, "iom"));
4122 static assert( hasStaticMember!(P, "iosf"));
4123 static assert(!hasStaticMember!(P, "p"));
4124 static assert( hasStaticMember!(P, "sp"));
4128 Retrieves the members of an enumerated type `enum E`.
4130 Params:
4131 E = An enumerated type. `E` may have duplicated values.
4133 Returns:
4134 Static tuple composed of the members of the enumerated type `E`.
4135 The members are arranged in the same order as declared in `E`.
4136 The name of the enum can be found by querying the compiler for the
4137 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`.
4138 For enumerations with unique values, $(REF to, std,conv) can also be used.
4140 Note:
4141 An enum can have multiple members which have the same value. If you want
4142 to use EnumMembers to e.g. generate switch cases at compile-time,
4143 you should use the $(REF NoDuplicates, std,meta) template to avoid
4144 generating duplicate switch cases.
4146 Note:
4147 Returned values are strictly typed with `E`. Thus, the following code
4148 does not work without the explicit cast:
4149 --------------------
4150 enum E : int { a, b, c }
4151 int[] abc = cast(int[]) [ EnumMembers!E ];
4152 --------------------
4153 Cast is not necessary if the type of the variable is inferred. See the
4154 example below.
4156 template EnumMembers(E)
4157 if (is(E == enum))
4159 alias EnumMembers = AliasSeq!();
4160 static foreach (M; __traits(allMembers, E))
4161 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, M));
4164 /// Create an array of enumerated values
4165 @safe unittest
4167 enum Sqrts : real
4169 one = 1,
4170 two = 1.41421,
4171 three = 1.73205
4173 auto sqrts = [EnumMembers!Sqrts];
4174 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
4178 A generic function `rank(v)` in the following example uses this
4179 template for finding a member `e` in an enumerated type `E`.
4181 @safe unittest
4183 // Returns i if e is the i-th enumerator of E.
4184 static size_t rank(E)(E e)
4185 if (is(E == enum))
4187 static foreach (i, member; EnumMembers!E)
4189 if (e == member)
4190 return i;
4192 assert(0, "Not an enum member");
4195 enum Mode
4197 read = 1,
4198 write = 2,
4199 map = 4
4201 assert(rank(Mode.read) == 0);
4202 assert(rank(Mode.write) == 1);
4203 assert(rank(Mode.map) == 2);
4207 Use EnumMembers to generate a switch statement using static foreach.
4210 @safe unittest
4212 import std.conv : to;
4213 class FooClass
4215 string calledMethod;
4216 void foo() @safe { calledMethod = "foo"; }
4217 void bar() @safe { calledMethod = "bar"; }
4218 void baz() @safe { calledMethod = "baz"; }
4221 enum FooEnum { foo, bar, baz }
4223 auto var = FooEnum.bar;
4224 auto fooObj = new FooClass();
4225 s: final switch (var)
4227 static foreach (member; EnumMembers!FooEnum)
4229 case member: // Generate a case for each enum value.
4230 // Call fooObj.{name of enum value}().
4231 __traits(getMember, fooObj, to!string(member))();
4232 break s;
4235 // As we pass in FooEnum.bar, the bar() method gets called.
4236 assert(fooObj.calledMethod == "bar");
4239 @safe unittest
4241 enum A { a }
4242 static assert([ EnumMembers!A ] == [ A.a ]);
4243 enum B { a, b, c, d, e }
4244 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]);
4247 @safe unittest // typed enums
4249 enum A : string { a = "alpha", b = "beta" }
4250 static assert([ EnumMembers!A ] == [ A.a, A.b ]);
4252 static struct S
4254 int value;
4255 int opCmp(S rhs) const nothrow { return value - rhs.value; }
4257 enum B : S { a = S(1), b = S(2), c = S(3) }
4258 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]);
4261 @safe unittest // duplicated values
4263 enum A
4265 a = 0, b = 0,
4266 c = 1, d = 1, e
4268 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]);
4271 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
4272 @safe unittest
4274 string genEnum()
4276 string result = "enum TLAs {";
4277 foreach (c0; '0'..'2'+1)
4278 foreach (c1; '0'..'9'+1)
4279 foreach (c2; '0'..'9'+1)
4280 foreach (c3; '0'..'9'+1)
4282 result ~= '_';
4283 result ~= c0;
4284 result ~= c1;
4285 result ~= c2;
4286 result ~= c3;
4287 result ~= ',';
4289 result ~= '}';
4290 return result;
4292 mixin(genEnum);
4293 static assert(EnumMembers!TLAs[0] == TLAs._0000);
4294 static assert(EnumMembers!TLAs[$-1] == TLAs._2999);
4297 @safe unittest
4299 enum E { member, a = 0, b = 0 }
4300 static assert(__traits(identifier, EnumMembers!E[0]) == "member");
4301 static assert(__traits(identifier, EnumMembers!E[1]) == "a");
4302 static assert(__traits(identifier, EnumMembers!E[2]) == "b");
4306 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4307 // Classes and Interfaces
4308 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4310 /***
4311 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
4312 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
4313 * the empty type tuple.
4315 template BaseTypeTuple(A)
4317 static if (is(A P == super))
4318 alias BaseTypeTuple = P;
4319 else
4320 static assert(0, "argument is not a class or interface");
4324 @safe unittest
4326 import std.meta : AliasSeq;
4328 interface I1 { }
4329 interface I2 { }
4330 interface I12 : I1, I2 { }
4331 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));
4333 interface I3 : I1 { }
4334 interface I123 : I1, I2, I3 { }
4335 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));
4338 @safe unittest
4340 interface I1 { }
4341 interface I2 { }
4342 class A { }
4343 class C : A, I1, I2 { }
4345 alias TL = BaseTypeTuple!C;
4346 assert(TL.length == 3);
4347 assert(is (TL[0] == A));
4348 assert(is (TL[1] == I1));
4349 assert(is (TL[2] == I2));
4351 assert(BaseTypeTuple!Object.length == 0);
4355 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4356 * in decreasing order. Interfaces are not included. $(D_PARAM
4357 * BaseClassesTuple!Object) yields the empty type tuple.
4359 template BaseClassesTuple(T)
4360 if (is(T == class))
4362 static if (is(T == Object))
4364 alias BaseClassesTuple = AliasSeq!();
4366 else static if (is(BaseTypeTuple!T[0] == Object))
4368 alias BaseClassesTuple = AliasSeq!Object;
4370 else static if (!is(BaseTypeTuple!T[0] == Object) && !is(BaseTypeTuple!T[0] == class))
4372 alias BaseClassesTuple = AliasSeq!();
4374 else
4376 alias BaseClassesTuple =
4377 AliasSeq!(BaseTypeTuple!T[0],
4378 BaseClassesTuple!(BaseTypeTuple!T[0]));
4383 @safe unittest
4385 import std.meta : AliasSeq;
4387 class C1 { }
4388 class C2 : C1 { }
4389 class C3 : C2 { }
4390 static assert(!BaseClassesTuple!Object.length);
4391 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
4392 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
4393 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));
4396 // https://issues.dlang.org/show_bug.cgi?id=17276
4397 @safe unittest
4399 extern (C++) static interface Ext
4401 void someext();
4404 extern (C++) static class E : Ext
4406 void someext() {}
4409 alias BaseClassesWithNoObject = BaseClassesTuple!E;
4412 @safe unittest
4414 struct S { }
4415 static assert(!__traits(compiles, BaseClassesTuple!S));
4416 interface I { }
4417 static assert(!__traits(compiles, BaseClassesTuple!I));
4418 class C4 : I { }
4419 class C5 : C4, I { }
4420 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object)));
4424 Params:
4425 T = The `class` or `interface` to search.
4427 Returns:
4428 $(REF AliasSeq,std,meta) of all interfaces directly or
4429 indirectly inherited by this class or interface. Interfaces
4430 do not repeat if multiply implemented.
4432 `InterfacesTuple!Object` yields an empty `AliasSeq`.
4434 template InterfacesTuple(T)
4436 import std.meta : NoDuplicates;
4437 template Flatten(H, T...)
4439 static if (T.length)
4441 alias Flatten = AliasSeq!(Flatten!H, Flatten!T);
4443 else
4445 static if (is(H == interface))
4446 alias Flatten = AliasSeq!(H, InterfacesTuple!H);
4447 else
4448 alias Flatten = InterfacesTuple!H;
4452 static if (is(T S == super) && S.length)
4453 alias InterfacesTuple = NoDuplicates!(Flatten!S);
4454 else
4455 alias InterfacesTuple = AliasSeq!();
4459 @safe unittest
4461 interface I1 {}
4462 interface I2 {}
4463 class A : I1, I2 {}
4464 class B : A, I1 {}
4465 class C : B {}
4467 alias TL = InterfacesTuple!C;
4468 static assert(is(TL[0] == I1) && is(TL[1] == I2));
4471 @safe unittest
4473 interface Iaa {}
4474 interface Iab {}
4475 interface Iba {}
4476 interface Ibb {}
4477 interface Ia : Iaa, Iab {}
4478 interface Ib : Iba, Ibb {}
4479 interface I : Ia, Ib {}
4480 interface J {}
4481 class B2 : J {}
4482 class C2 : B2, Ia, Ib {}
4483 static assert(is(InterfacesTuple!I ==
4484 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb)));
4485 static assert(is(InterfacesTuple!C2 ==
4486 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb)));
4491 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4492 * T), in decreasing order, followed by $(D_PARAM T)'s
4493 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4494 * empty type tuple.
4496 alias TransitiveBaseTypeTuple(T) = AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
4499 @safe unittest
4501 interface J1 {}
4502 interface J2 {}
4503 class B1 {}
4504 class B2 : B1, J1, J2 {}
4505 class B3 : B2, J1 {}
4506 alias TL = TransitiveBaseTypeTuple!B3;
4507 assert(TL.length == 5);
4508 assert(is (TL[0] == B2));
4509 assert(is (TL[1] == B1));
4510 assert(is (TL[2] == Object));
4511 assert(is (TL[3] == J1));
4512 assert(is (TL[4] == J2));
4514 assert(TransitiveBaseTypeTuple!Object.length == 0);
4519 Returns a tuple of non-static functions with the name `name` declared in the
4520 class or interface `C`. Covariant duplicates are shrunk into the most
4521 derived one.
4523 template MemberFunctionsTuple(C, string name)
4524 if (is(C == class) || is(C == interface))
4526 static if (__traits(hasMember, C, name))
4529 * First, collect all overloads in the class hierarchy.
4531 template CollectOverloads(Node)
4533 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
4535 // Get all overloads in sight (not hidden).
4536 alias inSight = __traits(getVirtualMethods, Node, name);
4538 // And collect all overloads in ancestor classes to reveal hidden
4539 // methods. The result may contain duplicates.
4540 template walkThru(Parents...)
4542 static if (Parents.length > 0)
4543 alias walkThru = AliasSeq!(
4544 CollectOverloads!(Parents[0]),
4545 walkThru!(Parents[1 .. $])
4547 else
4548 alias walkThru = AliasSeq!();
4551 static if (is(Node Parents == super))
4552 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents);
4553 else
4554 alias CollectOverloads = AliasSeq!inSight;
4556 else
4557 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy
4560 static if (name == "__ctor" || name == "__dtor")
4561 alias overloads = AliasSeq!(__traits(getOverloads, C, name));
4562 else
4563 // duplicates in this tuple will be removed by shrink()
4564 alias overloads = CollectOverloads!C;
4566 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4567 // shrinkOne!args[1..$] = non-covariant others
4568 template shrinkOne(/+ alias target, rest... +/ args...)
4570 import std.meta : AliasSeq;
4571 alias target = args[0 .. 1]; // prevent property functions from being evaluated
4572 alias rest = args[1 .. $];
4574 static if (rest.length > 0)
4576 alias Target = FunctionTypeOf!target;
4577 alias Rest0 = FunctionTypeOf!(rest[0]);
4579 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target))
4581 // One of these overrides the other. Choose the one from the most derived parent.
4582 static if (is(__traits(parent, target) : __traits(parent, rest[0])))
4583 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4584 else
4585 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4587 else static if (isCovariantWith!(Target, Rest0))
4588 // target overrides rest[0] -- erase rest[0].
4589 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4590 else static if (isCovariantWith!(Rest0, Target))
4591 // rest[0] overrides target -- erase target.
4592 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4593 else
4594 // target and rest[0] are distinct.
4595 alias shrinkOne = AliasSeq!(
4596 shrinkOne!(target, rest[1 .. $]),
4597 rest[0] // keep
4600 else
4601 alias shrinkOne = AliasSeq!target; // done
4605 * Now shrink covariant overloads into one.
4607 template shrink(overloads...)
4609 static if (overloads.length > 0)
4611 alias temp = shrinkOne!overloads;
4612 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $]));
4614 else
4615 alias shrink = AliasSeq!(); // done
4618 // done.
4619 alias MemberFunctionsTuple = shrink!overloads;
4621 else
4622 alias MemberFunctionsTuple = AliasSeq!();
4626 @safe unittest
4628 interface I { I foo(); }
4629 class B
4631 real foo(real v) { return v; }
4633 class C : B, I
4635 override C foo() { return this; } // covariant overriding of I.foo()
4637 alias foos = MemberFunctionsTuple!(C, "foo");
4638 static assert(foos.length == 2);
4639 static assert(__traits(isSame, foos[0], C.foo));
4640 static assert(__traits(isSame, foos[1], B.foo));
4643 // https://issues.dlang.org/show_bug.cgi?id=15920
4644 @safe unittest
4646 import std.meta : AliasSeq;
4647 class A
4649 void f(){}
4650 void f(int){}
4652 class B : A
4654 override void f(){}
4655 override void f(int){}
4657 alias fs = MemberFunctionsTuple!(B, "f");
4658 alias bfs = __traits(getOverloads, B, "f");
4659 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1]));
4660 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1]));
4663 // https://issues.dlang.org/show_bug.cgi?id=8388
4664 @safe unittest
4666 class C
4668 this() {}
4669 this(int i) {}
4670 this(int i, float j) {}
4671 this(string s) {}
4674 Commented out, because this causes a cyclic dependency
4675 between module constructors/destructors error. Might
4676 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */
4677 // static this() {}
4679 ~this() {}
4682 class D : C
4684 this() {}
4685 ~this() {}
4688 alias test_ctor = MemberFunctionsTuple!(C, "__ctor");
4689 assert(test_ctor.length == 4);
4690 alias test_dtor = MemberFunctionsTuple!(C, "__dtor");
4691 assert(test_dtor.length == 1);
4692 alias test2_ctor = MemberFunctionsTuple!(D, "__ctor");
4693 assert(test2_ctor.length == 1);
4694 alias test2_dtor = MemberFunctionsTuple!(D, "__dtor");
4695 assert(test2_dtor.length == 1);
4698 @safe unittest
4700 interface I { I test(); }
4701 interface J : I { J test(); }
4702 interface K { K test(int); }
4703 class B : I, K
4705 K test(int) { return this; }
4706 B test() { return this; }
4707 static void test(string) { }
4709 class C : B, J
4711 override C test() { return this; }
4713 alias test =MemberFunctionsTuple!(C, "test");
4714 static assert(test.length == 2);
4715 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test)));
4716 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test)));
4717 alias noexist = MemberFunctionsTuple!(C, "noexist");
4718 static assert(noexist.length == 0);
4720 interface L { int prop() @property; }
4721 alias prop = MemberFunctionsTuple!(L, "prop");
4722 static assert(prop.length == 1);
4724 interface Test_I
4726 void foo();
4727 void foo(int);
4728 void foo(int, int);
4730 interface Test : Test_I {}
4731 alias Test_foo = MemberFunctionsTuple!(Test, "foo");
4732 static assert(Test_foo.length == 3);
4733 static assert(is(typeof(&Test_foo[0]) == void function()));
4734 static assert(is(typeof(&Test_foo[2]) == void function(int)));
4735 static assert(is(typeof(&Test_foo[1]) == void function(int, int)));
4740 Returns an alias to the template that `T` is an instance of.
4741 It will return `void` if a symbol without a template is given.
4743 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
4745 /// ditto
4746 alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
4748 /// ditto
4749 alias TemplateOf(T) = void;
4752 @safe unittest
4754 struct Foo(T, U) {}
4755 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4758 @safe unittest
4760 template Foo1(A) {}
4761 template Foo2(A, B) {}
4762 template Foo3(alias A) {}
4763 template Foo4(string A) {}
4764 struct Foo5(A) {}
4765 struct Foo6(A, B) {}
4766 struct Foo7(alias A) {}
4767 template Foo8(A) { template Foo9(B) {} }
4768 template Foo10() {}
4770 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4771 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4772 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4773 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4774 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4775 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4776 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4777 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4778 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4781 // https://issues.dlang.org/show_bug.cgi?id=18214
4782 @safe unittest
4784 static assert(is(TemplateOf!(int[]) == void));
4785 static assert(is(TemplateOf!bool == void));
4789 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4791 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4793 /// ditto
4794 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4797 @safe unittest
4799 import std.meta : AliasSeq;
4801 struct Foo(T, U) {}
4802 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4805 @safe unittest
4807 template Foo1(A) {}
4808 template Foo2(A, B) {}
4809 template Foo3(alias A) {}
4810 template Foo4(string A) {}
4811 struct Foo5(A) {}
4812 struct Foo6(A, B) {}
4813 struct Foo7(alias A) {}
4814 template Foo8(A) { template Foo9(B) {} }
4815 template Foo10() {}
4817 enum x = 123;
4818 enum y = "123";
4819 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4820 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4821 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4822 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4823 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4824 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4825 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4826 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4827 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4830 // Returns the largest alignment in a type tuple.
4831 package enum maxAlignment(U...) =
4833 size_t result = U[0].alignof;
4834 static foreach (T; U[1 .. $])
4835 if (result < T.alignof)
4836 result = T.alignof;
4837 return result;
4838 }();
4841 Returns class instance alignment.
4843 template classInstanceAlignment(T)
4844 if (is(T == class))
4846 enum classInstanceAlignment = __traits(classInstanceAlignment, T);
4850 @safe unittest
4852 class A { byte b; }
4853 class B { long l; }
4855 // As class instance always has a hidden pointer
4856 static assert(classInstanceAlignment!A == (void*).alignof);
4857 static assert(classInstanceAlignment!B == long.alignof);
4861 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4862 // Type Conversion
4863 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4866 Get the type that all types can be implicitly converted to. Useful
4867 e.g. in figuring out an array type from a bunch of initializing
4868 values. Returns $(D_PARAM void) if passed an empty list, or if the
4869 types have no common type.
4871 template CommonType(T...)
4873 static if (T.length == 1)
4874 alias CommonType = typeof(T[0].init);
4875 else static if (is(typeof(true ? T[0].init : T[1].init) U))
4876 alias CommonType = CommonType!(U, T[2 .. $]);
4877 else
4878 alias CommonType = void;
4882 @safe unittest
4884 alias X = CommonType!(int, long, short);
4885 assert(is(X == long));
4886 alias Y = CommonType!(int, char[], short);
4887 assert(is(Y == void));
4891 @safe unittest
4893 static assert(is(CommonType!(3) == int));
4894 static assert(is(CommonType!(double, 4, float) == double));
4895 static assert(is(CommonType!(string, char[]) == const(char)[]));
4896 static assert(is(CommonType!(3, 3U) == uint));
4897 static assert(is(CommonType!(double, int) == double));
4902 Params:
4903 T = The type to check
4905 Returns:
4906 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4907 conversion `T`.
4909 If `T` is a class derived from `Object`, the result of
4910 $(LREF TransitiveBaseTypeTuple) is returned.
4912 If the type is not a built-in value type or a class derived from
4913 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4915 See_Also:
4916 $(LREF isImplicitlyConvertible)
4918 template AllImplicitConversionTargets(T)
4920 static if (is(T == bool))
4921 alias AllImplicitConversionTargets =
4922 AliasSeq!(byte, AllImplicitConversionTargets!byte);
4923 else static if (is(T == byte))
4924 alias AllImplicitConversionTargets =
4925 AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4926 else static if (is(T == ubyte))
4927 alias AllImplicitConversionTargets =
4928 AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4929 else static if (is(T == short))
4930 alias AllImplicitConversionTargets =
4931 AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4932 else static if (is(T == ushort))
4933 alias AllImplicitConversionTargets =
4934 AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4935 else static if (is(T == int))
4936 alias AllImplicitConversionTargets =
4937 AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4938 else static if (is(T == uint))
4939 alias AllImplicitConversionTargets =
4940 AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4941 else static if (is(T == long))
4942 alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4943 else static if (is(T == ulong))
4944 alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4945 else static if (is(T == float))
4946 alias AllImplicitConversionTargets = AliasSeq!(double, real);
4947 else static if (is(T == double))
4948 alias AllImplicitConversionTargets = AliasSeq!(float, real);
4949 else static if (is(T == real))
4950 alias AllImplicitConversionTargets = AliasSeq!(float, double);
4951 else static if (is(T == char))
4952 alias AllImplicitConversionTargets =
4953 AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4954 else static if (is(T == wchar))
4955 alias AllImplicitConversionTargets =
4956 AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4957 else static if (is(T == dchar))
4958 alias AllImplicitConversionTargets =
4959 AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4960 else static if (is(T == class))
4961 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4962 else static if (is(T == interface))
4963 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4964 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4966 static if (is(typeof(T.init[0]) == shared))
4967 alias AllImplicitConversionTargets =
4968 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4969 else
4970 alias AllImplicitConversionTargets =
4971 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4973 else static if (is(T : void*) && !is(T == void*))
4974 alias AllImplicitConversionTargets = AliasSeq!(void*);
4975 else static if (is(cent) && is(T == cent))
4976 alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4977 else static if (is(ucent) && is(T == ucent))
4978 alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4979 else
4980 alias AllImplicitConversionTargets = AliasSeq!();
4984 @safe unittest
4986 import std.meta : AliasSeq;
4988 static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4989 static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4990 static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4991 static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4993 static assert(is(AllImplicitConversionTargets!(char) ==
4994 AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4995 ulong, float, double, real)
4997 static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4998 short, ushort, dchar, int, uint, long, ulong, float, double, real
4999 )));
5000 static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
5001 int, uint, long, ulong, float, double, real
5002 )));
5004 static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5005 static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
5007 interface A {}
5008 interface B {}
5009 class C : A, B {}
5011 static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5012 static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5013 static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
5014 immutable Object, immutable A, immutable B
5015 )));
5017 interface I : A, B {}
5019 static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
5020 static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
5021 static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
5022 immutable A, immutable B
5023 )));
5026 @safe unittest
5028 static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5029 static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5030 static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5035 Params:
5036 T = The type to check
5038 Warning:
5039 This template is considered out-dated. It will be removed from
5040 Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5042 Returns:
5043 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5044 conversion `T`.
5046 If `T` is a class derived from `Object`, the result of
5047 $(LREF TransitiveBaseTypeTuple) is returned.
5049 If the type is not a built-in value type or a class derived from
5050 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5052 Note:
5053 The possible targets are computed more conservatively than the
5054 language allows, eliminating all dangerous conversions. For example,
5055 `ImplicitConversionTargets!double` does not include `float`.
5057 See_Also:
5058 $(LREF isImplicitlyConvertible)
5060 // @@@DEPRECATED_[2.107.0]@@@
5061 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5062 ~ "and will be removed in 2.107.0")
5063 template ImplicitConversionTargets(T)
5065 static if (is(T == bool))
5066 alias ImplicitConversionTargets =
5067 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5068 float, double, real, char, wchar, dchar);
5069 else static if (is(T == byte))
5070 alias ImplicitConversionTargets =
5071 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5072 float, double, real, char, wchar, dchar);
5073 else static if (is(T == ubyte))
5074 alias ImplicitConversionTargets =
5075 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5076 float, double, real, char, wchar, dchar);
5077 else static if (is(T == short))
5078 alias ImplicitConversionTargets =
5079 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5080 else static if (is(T == ushort))
5081 alias ImplicitConversionTargets =
5082 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5083 else static if (is(T == int))
5084 alias ImplicitConversionTargets =
5085 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5086 else static if (is(T == uint))
5087 alias ImplicitConversionTargets =
5088 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5089 else static if (is(T == long))
5090 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5091 else static if (is(T == ulong))
5092 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5093 else static if (is(cent) && is(T == cent))
5094 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5095 else static if (is(ucent) && is(T == ucent))
5096 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5097 else static if (is(T == float))
5098 alias ImplicitConversionTargets = AliasSeq!(double, real);
5099 else static if (is(T == double))
5100 alias ImplicitConversionTargets = AliasSeq!real;
5101 else static if (is(T == char))
5102 alias ImplicitConversionTargets =
5103 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5104 int, uint, long, ulong, CentTypeList, float, double, real);
5105 else static if (is(T == wchar))
5106 alias ImplicitConversionTargets =
5107 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5108 float, double, real);
5109 else static if (is(T == dchar))
5110 alias ImplicitConversionTargets =
5111 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5112 else static if (is(T : typeof(null)))
5113 alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5114 else static if (is(T == class))
5115 alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5116 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5118 static if (is(typeof(T.init[0]) == shared))
5119 alias ImplicitConversionTargets =
5120 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5121 else
5122 alias ImplicitConversionTargets =
5123 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5125 else static if (is(T : void*))
5126 alias ImplicitConversionTargets = AliasSeq!(void*);
5127 else
5128 alias ImplicitConversionTargets = AliasSeq!();
5131 deprecated @safe unittest
5133 import std.meta : AliasSeq;
5135 static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5136 static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5137 static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5138 static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5140 static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5141 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5142 )));
5143 static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5144 dchar, short, ushort, int, uint, long, ulong, float, double, real
5145 )));
5146 static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5147 int, uint, long, ulong, float, double, real
5148 )));
5150 static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5151 static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5153 interface A {}
5154 interface B {}
5155 class C : A, B {}
5157 static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5158 static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5159 static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5160 immutable Object, immutable A, immutable B
5161 )));
5164 deprecated @safe unittest
5166 static assert(is(ImplicitConversionTargets!(double)[0] == real));
5167 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5171 Is `From` implicitly convertible to `To`?
5173 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5176 @safe unittest
5178 static assert( isImplicitlyConvertible!(immutable(char), char));
5179 static assert( isImplicitlyConvertible!(const(char), char));
5180 static assert( isImplicitlyConvertible!(char, wchar));
5181 static assert(!isImplicitlyConvertible!(wchar, char));
5183 static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5184 static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5185 static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5187 static assert(!isImplicitlyConvertible!(const(char)[], string));
5188 static assert( isImplicitlyConvertible!(string, const(char)[]));
5192 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5193 type `Lhs`.
5195 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5197 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5199 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5202 @safe unittest
5204 static assert( isAssignable!(long, int));
5205 static assert(!isAssignable!(int, long));
5206 static assert( isAssignable!(const(char)[], string));
5207 static assert(!isAssignable!(string, char[]));
5209 // int is assignable to int
5210 static assert( isAssignable!int);
5212 // immutable int is not assignable to immutable int
5213 static assert(!isAssignable!(immutable int));
5217 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5218 type `Lhs`.
5220 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5223 @safe unittest
5225 struct S1
5227 void opAssign(S1);
5230 struct S2
5232 void opAssign(ref S2);
5235 static assert( isRvalueAssignable!(long, int));
5236 static assert(!isRvalueAssignable!(int, long));
5237 static assert( isRvalueAssignable!S1);
5238 static assert(!isRvalueAssignable!S2);
5242 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5243 type `Lhs`.
5245 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5248 @safe unittest
5250 struct S1
5252 void opAssign(S1);
5255 struct S2
5257 void opAssign(ref S2);
5260 static assert( isLvalueAssignable!(long, int));
5261 static assert(!isLvalueAssignable!(int, long));
5262 static assert( isLvalueAssignable!S1);
5263 static assert( isLvalueAssignable!S2);
5266 @safe unittest
5268 static assert(!isAssignable!(immutable int, int));
5269 static assert( isAssignable!(int, immutable int));
5271 static assert(!isAssignable!(inout int, int));
5272 static assert( isAssignable!(int, inout int));
5273 static assert(!isAssignable!(inout int));
5275 static assert( isAssignable!(shared int, int));
5276 static assert( isAssignable!(int, shared int));
5277 static assert( isAssignable!(shared int));
5279 static assert( isAssignable!(void[1], void[1]));
5281 struct S { @disable this(); this(int n){} }
5282 static assert( isAssignable!(S, S));
5284 struct S2 { this(int n){} }
5285 static assert( isAssignable!(S2, S2));
5286 static assert(!isAssignable!(S2, int));
5288 struct S3 { @disable void opAssign(); }
5289 static assert( isAssignable!(S3, S3));
5291 struct S3X { @disable void opAssign(S3X); }
5292 static assert(!isAssignable!(S3X, S3X));
5294 struct S4 { void opAssign(int); }
5295 static assert( isAssignable!(S4, S4));
5296 static assert( isAssignable!(S4, int));
5297 static assert( isAssignable!(S4, immutable int));
5299 struct S5 { @disable this(); @disable this(this); }
5300 // https://issues.dlang.org/show_bug.cgi?id=21210
5301 static assert(!isAssignable!S5);
5303 // `-preview=in` is enabled
5304 alias DScannerBug895 = int[256];
5305 static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
5307 struct S6 { void opAssign(in S5); }
5309 static assert(isRvalueAssignable!(S6, S5));
5310 static assert(isLvalueAssignable!(S6, S5));
5311 static assert(isAssignable!(S6, S5));
5312 static assert(isAssignable!(S6, immutable S5));
5314 else
5316 mixin(q{ struct S6 { void opAssign(in ref S5); } });
5318 static assert(!isRvalueAssignable!(S6, S5));
5319 static assert( isLvalueAssignable!(S6, S5));
5320 static assert(!isAssignable!(S6, S5));
5321 static assert( isLvalueAssignable!(S6, immutable S5));
5326 // Equivalent with TypeStruct::isAssignable in compiler code.
5327 package template isBlitAssignable(T)
5329 static if (is(T == enum))
5331 enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5333 else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5334 // Workaround for issue 11499 : isStaticArray!T should not be necessary.
5336 enum isBlitAssignable = isBlitAssignable!E;
5338 else static if (is(T == struct) || is(T == union))
5340 enum isBlitAssignable = isMutable!T &&
5342 size_t offset = 0;
5343 bool assignable = true;
5344 foreach (i, F; FieldTypeTuple!T)
5346 static if (i == 0)
5349 else
5351 if (T.tupleof[i].offsetof == offset)
5353 if (assignable)
5354 continue;
5356 else
5358 if (!assignable)
5359 return false;
5362 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5363 offset = T.tupleof[i].offsetof;
5365 return assignable;
5366 }();
5368 else
5369 enum isBlitAssignable = isMutable!T;
5372 @safe unittest
5374 static assert( isBlitAssignable!int);
5375 static assert(!isBlitAssignable!(const int));
5377 class C{ const int i; }
5378 static assert( isBlitAssignable!C);
5380 struct S1{ int i; }
5381 struct S2{ const int i; }
5382 static assert( isBlitAssignable!S1);
5383 static assert(!isBlitAssignable!S2);
5385 struct S3X { union { int x; int y; } }
5386 struct S3Y { union { int x; const int y; } }
5387 struct S3Z { union { const int x; const int y; } }
5388 static assert( isBlitAssignable!(S3X));
5389 static assert( isBlitAssignable!(S3Y));
5390 static assert(!isBlitAssignable!(S3Z));
5391 static assert(!isBlitAssignable!(const S3X));
5392 static assert(!isBlitAssignable!(inout S3Y));
5393 static assert(!isBlitAssignable!(immutable S3Z));
5394 static assert( isBlitAssignable!(S3X[3]));
5395 static assert( isBlitAssignable!(S3Y[3]));
5396 static assert(!isBlitAssignable!(S3Z[3]));
5397 enum ES3X : S3X { a = S3X() }
5398 enum ES3Y : S3Y { a = S3Y() }
5399 enum ES3Z : S3Z { a = S3Z() }
5400 static assert( isBlitAssignable!(ES3X));
5401 static assert( isBlitAssignable!(ES3Y));
5402 static assert(!isBlitAssignable!(ES3Z));
5403 static assert(!isBlitAssignable!(const ES3X));
5404 static assert(!isBlitAssignable!(inout ES3Y));
5405 static assert(!isBlitAssignable!(immutable ES3Z));
5406 static assert( isBlitAssignable!(ES3X[3]));
5407 static assert( isBlitAssignable!(ES3Y[3]));
5408 static assert(!isBlitAssignable!(ES3Z[3]));
5410 union U1X { int x; int y; }
5411 union U1Y { int x; const int y; }
5412 union U1Z { const int x; const int y; }
5413 static assert( isBlitAssignable!(U1X));
5414 static assert( isBlitAssignable!(U1Y));
5415 static assert(!isBlitAssignable!(U1Z));
5416 static assert(!isBlitAssignable!(const U1X));
5417 static assert(!isBlitAssignable!(inout U1Y));
5418 static assert(!isBlitAssignable!(immutable U1Z));
5419 static assert( isBlitAssignable!(U1X[3]));
5420 static assert( isBlitAssignable!(U1Y[3]));
5421 static assert(!isBlitAssignable!(U1Z[3]));
5422 enum EU1X : U1X { a = U1X() }
5423 enum EU1Y : U1Y { a = U1Y() }
5424 enum EU1Z : U1Z { a = U1Z() }
5425 static assert( isBlitAssignable!(EU1X));
5426 static assert( isBlitAssignable!(EU1Y));
5427 static assert(!isBlitAssignable!(EU1Z));
5428 static assert(!isBlitAssignable!(const EU1X));
5429 static assert(!isBlitAssignable!(inout EU1Y));
5430 static assert(!isBlitAssignable!(immutable EU1Z));
5431 static assert( isBlitAssignable!(EU1X[3]));
5432 static assert( isBlitAssignable!(EU1Y[3]));
5433 static assert(!isBlitAssignable!(EU1Z[3]));
5435 struct SA
5437 @property int[3] foo() { return [1,2,3]; }
5438 alias foo this;
5439 const int x; // SA is not blit assignable
5441 static assert(!isStaticArray!SA);
5442 static assert(!isBlitAssignable!(SA[3]));
5447 Works like `isImplicitlyConvertible`, except this cares only about storage
5448 classes of the arguments.
5450 private template isStorageClassImplicitlyConvertible(From, To)
5452 alias Pointify(T) = void*;
5454 enum isStorageClassImplicitlyConvertible = is(
5455 ModifyTypePreservingTQ!(Pointify, From) :
5456 ModifyTypePreservingTQ!(Pointify, To) );
5459 @safe unittest
5461 static assert( isStorageClassImplicitlyConvertible!( int, const int));
5462 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5464 static assert(!isStorageClassImplicitlyConvertible!(const int, int));
5465 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5466 static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5467 static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5472 Determines whether the function type `F` is covariant with `G`, i.e.,
5473 functions of the type `F` can override ones of the type `G`.
5475 template isCovariantWith(F, G)
5476 if (is(F == function) && is(G == function) ||
5477 is(F == delegate) && is(G == delegate) ||
5478 isFunctionPointer!F && isFunctionPointer!G)
5480 static if (is(F : G))
5481 enum isCovariantWith = true;
5482 else
5484 alias Upr = F;
5485 alias Lwr = G;
5488 * Check for calling convention: require exact match.
5490 template checkLinkage()
5492 enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5495 * Check for variadic parameter: require exact match.
5497 template checkVariadicity()
5499 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5502 * Check for function storage class:
5503 * - overrider can have narrower storage class than base
5505 template checkSTC()
5507 // Note the order of arguments. The convertion order Lwr -> Upr is
5508 // correct since Upr should be semantically 'narrower' than Lwr.
5509 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5512 * Check for function attributes:
5513 * - require exact match for ref and @property
5514 * - overrider can add pure and nothrow, but can't remove them
5515 * - @safe and @trusted are covariant with each other, unremovable
5517 template checkAttributes()
5519 alias FA = FunctionAttribute;
5520 enum uprAtts = functionAttributes!Upr;
5521 enum lwrAtts = functionAttributes!Lwr;
5523 enum wantExact = FA.ref_ | FA.property;
5524 enum safety = FA.safe | FA.trusted;
5525 enum ok =
5526 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) &&
5527 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) &&
5528 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5529 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ;
5532 * Check for return type: usual implicit convertion.
5534 template checkReturnType()
5536 enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5539 * Check for parameters:
5540 * - require exact match for types
5541 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5542 * - require exact match for in, out, ref and lazy
5543 * - overrider can add scope, but can't remove
5545 template checkParameters()
5547 alias STC = ParameterStorageClass;
5548 alias UprParams = Parameters!Upr;
5549 alias LwrParams = Parameters!Lwr;
5550 alias UprPSTCs = ParameterStorageClassTuple!Upr;
5551 alias LwrPSTCs = ParameterStorageClassTuple!Lwr;
5553 template checkNext(size_t i)
5555 static if (i < UprParams.length)
5557 enum uprStc = UprPSTCs[i];
5558 enum lwrStc = LwrPSTCs[i];
5560 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5561 enum ok =
5562 ((uprStc & wantExact ) == (lwrStc & wantExact )) &&
5563 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) &&
5564 checkNext!(i + 1).ok;
5566 else
5567 enum ok = true; // done
5569 static if (UprParams.length == LwrParams.length)
5570 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5571 else
5572 enum ok = false;
5575 /* run all the checks */
5576 enum isCovariantWith =
5577 checkLinkage !().ok &&
5578 checkVariadicity!().ok &&
5579 checkSTC !().ok &&
5580 checkAttributes !().ok &&
5581 checkReturnType !().ok &&
5582 checkParameters !().ok ;
5587 @safe unittest
5589 interface I { I clone(); }
5590 interface J { J clone(); }
5591 class C : I
5593 override C clone() // covariant overriding of I.clone()
5595 return new C;
5599 // C.clone() can override I.clone(), indeed.
5600 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5602 // C.clone() can't override J.clone(); the return type C is not implicitly
5603 // convertible to J.
5604 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5607 @safe unittest
5609 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5611 // covariant return type
5612 interface I {}
5613 interface J : I {}
5614 interface BaseA { const(I) test(int); }
5615 interface DerivA_1 : BaseA { override const(J) test(int); }
5616 interface DerivA_2 : BaseA { override J test(int); }
5617 static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5618 static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5619 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5620 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5621 static assert( isCovariantWith!(BaseA.test, BaseA.test));
5622 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5623 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5625 // function, function pointer and delegate
5626 J function() derived_function;
5627 I function() base_function;
5628 J delegate() derived_delegate;
5629 I delegate() base_delegate;
5630 static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5631 static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5632 static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5634 // scope parameter
5635 interface BaseB { void test( int*, int*); }
5636 interface DerivB_1 : BaseB { override void test(scope int*, int*); }
5637 interface DerivB_2 : BaseB { override void test( int*, scope int*); }
5638 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5639 static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5640 static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5641 static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5642 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5643 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5644 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5646 // function storage class
5647 interface BaseC { void test() ; }
5648 interface DerivC_1 : BaseC { override void test() const; }
5649 static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5650 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5652 // increasing safety
5653 interface BaseE { void test() ; }
5654 interface DerivE_1 : BaseE { override void test() @safe ; }
5655 interface DerivE_2 : BaseE { override void test() @trusted; }
5656 static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5657 static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5658 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5659 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5661 // @safe and @trusted
5662 interface BaseF
5664 void test1() @safe;
5665 void test2() @trusted;
5667 interface DerivF : BaseF
5669 override void test1() @trusted;
5670 override void test2() @safe;
5672 static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5673 static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5677 // Needed for rvalueOf/lvalueOf because "inout on return means
5678 // inout must be on a parameter as well"
5679 private struct __InoutWorkaroundStruct{}
5682 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5683 `__traits(compiles, ...)` purposes. No actual value is returned.
5685 Params:
5686 T = The type to transform
5688 Note: Trying to use returned value will result in a
5689 "Symbol Undefined" error at link time.
5691 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5693 /// ditto
5694 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5696 // Note: can't put these unittests together as function overloads
5697 // aren't allowed inside functions.
5699 @system unittest
5701 static int f(int);
5702 static assert(is(typeof(f(rvalueOf!int)) == int));
5706 @system unittest
5708 static bool f(ref int);
5709 static assert(is(typeof(f(lvalueOf!int)) == bool));
5712 @system unittest
5714 void needLvalue(T)(ref T);
5715 static struct S { }
5716 int i;
5717 struct Nested { void f() { ++i; } }
5718 static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5720 static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5721 static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5722 static assert(is(typeof(rvalueOf!T) == T));
5723 static assert(is(typeof(lvalueOf!T) == T));
5726 static assert(!__traits(compiles, rvalueOf!int = 1));
5727 static assert( __traits(compiles, lvalueOf!byte = 127));
5728 static assert(!__traits(compiles, lvalueOf!byte = 128));
5732 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5733 // SomethingTypeOf
5734 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5738 template BooleanTypeOf(T)
5740 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5741 alias X = BooleanTypeOf!AT;
5742 else
5743 alias X = OriginalType!T;
5745 static if (is(immutable X == immutable bool))
5747 alias BooleanTypeOf = X;
5749 else
5750 static assert(0, T.stringof~" is not boolean type");
5753 @safe unittest
5755 // unexpected failure, maybe dmd type-merging bug
5756 static foreach (T; AliasSeq!bool)
5757 static foreach (Q; TypeQualifierList)
5759 static assert( is(Q!T == BooleanTypeOf!( Q!T )));
5760 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5763 static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5764 static foreach (Q; TypeQualifierList)
5766 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof);
5767 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5771 @safe unittest
5773 struct B
5775 bool val;
5776 alias val this;
5778 struct S
5780 B b;
5781 alias b this;
5783 static assert(is(BooleanTypeOf!B == bool));
5784 static assert(is(BooleanTypeOf!S == bool));
5789 template IntegralTypeOf(T)
5791 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5792 alias X = IntegralTypeOf!AT;
5793 else
5794 alias X = OriginalType!T;
5796 static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5797 && !is(immutable X == immutable bool) && !is(X == __vector))
5799 alias IntegralTypeOf = X;
5801 else
5802 static assert(0, T.stringof~" is not an integral type");
5805 @safe unittest
5807 static foreach (T; IntegralTypeList)
5808 static foreach (Q; TypeQualifierList)
5810 static assert( is(Q!T == IntegralTypeOf!( Q!T )));
5811 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5814 static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5815 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5816 static foreach (Q; TypeQualifierList)
5818 static assert(!is(IntegralTypeOf!( Q!T )));
5819 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5825 template FloatingPointTypeOf(T)
5827 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5828 alias X = FloatingPointTypeOf!AT;
5829 else
5830 alias X = OriginalType!T;
5832 static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5834 alias FloatingPointTypeOf = X;
5836 else
5837 static assert(0, T.stringof~" is not a floating point type");
5840 @safe unittest
5842 static foreach (T; FloatingPointTypeList)
5843 static foreach (Q; TypeQualifierList)
5845 static assert( is(Q!T == FloatingPointTypeOf!( Q!T )));
5846 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5849 static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5850 static foreach (Q; TypeQualifierList)
5852 static assert(!is(FloatingPointTypeOf!( Q!T )));
5853 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5859 template NumericTypeOf(T)
5861 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5863 alias NumericTypeOf = X;
5865 else
5866 static assert(0, T.stringof~" is not a numeric type");
5869 @safe unittest
5871 static foreach (T; NumericTypeList)
5872 static foreach (Q; TypeQualifierList)
5874 static assert( is(Q!T == NumericTypeOf!( Q!T )));
5875 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5878 static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5879 static foreach (Q; TypeQualifierList)
5881 static assert(!is(NumericTypeOf!( Q!T )));
5882 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5888 template UnsignedTypeOf(T)
5890 static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5891 alias UnsignedTypeOf = X;
5892 else
5893 static assert(0, T.stringof~" is not an unsigned type.");
5898 template SignedTypeOf(T)
5900 static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5901 alias SignedTypeOf = X;
5902 else static if (is(FloatingPointTypeOf!T X))
5903 alias SignedTypeOf = X;
5904 else
5905 static assert(0, T.stringof~" is not an signed type.");
5910 template CharTypeOf(T)
5912 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5913 alias X = CharTypeOf!AT;
5914 else
5915 alias X = OriginalType!T;
5917 static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5919 alias CharTypeOf = X;
5921 else
5922 static assert(0, T.stringof~" is not a character type");
5925 @safe unittest
5927 static foreach (T; CharTypeList)
5928 static foreach (Q; TypeQualifierList)
5930 static assert( is(CharTypeOf!( Q!T )));
5931 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5934 static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5935 static foreach (Q; TypeQualifierList)
5937 static assert(!is(CharTypeOf!( Q!T )));
5938 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5941 static foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5942 static foreach (Q; TypeQualifierList)
5944 static assert(!is(CharTypeOf!( Q!T )));
5945 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5951 template StaticArrayTypeOf(T)
5953 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5954 alias X = StaticArrayTypeOf!AT;
5955 else
5956 alias X = OriginalType!T;
5958 static if (__traits(isStaticArray, X))
5959 alias StaticArrayTypeOf = X;
5960 else
5961 static assert(0, T.stringof~" is not a static array type");
5964 @safe unittest
5966 static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5967 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5969 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) ));
5971 static foreach (P; TypeQualifierList)
5972 { // SubTypeOf cannot have inout type
5973 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
5977 static foreach (T; AliasSeq!void)
5978 static foreach (Q; AliasSeq!TypeQualifierList)
5980 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
5986 template DynamicArrayTypeOf(T)
5988 import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
5989 alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
5992 @safe unittest
5994 import std.meta : Alias;
5995 static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5996 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5998 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) ));
5999 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) ));
6001 static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
6003 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
6004 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
6008 static assert(!is(DynamicArrayTypeOf!(int[3])));
6009 static assert(!is(DynamicArrayTypeOf!(void[3])));
6010 static assert(!is(DynamicArrayTypeOf!(typeof(null))));
6015 template ArrayTypeOf(T)
6017 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
6019 alias ArrayTypeOf = X;
6021 else
6022 static assert(0, T.stringof~" is not an array type");
6026 * Converts strings and string-like types to the corresponding dynamic array of characters.
6027 * Params:
6028 * T = one of the following:
6029 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6030 * (`shared` is rejected)
6031 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6032 * (`shared` is rejected)
6033 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6035 * Other cases are rejected with a compile time error.
6036 * `typeof(null)` is rejected.
6038 * Returns:
6039 * The result of `[]` applied to the qualified character type.
6041 template StringTypeOf(T)
6043 static if (is(T == typeof(null)))
6045 // It is impossible to determine exact string type from typeof(null) -
6046 // it means that StringTypeOf!(typeof(null)) is undefined.
6047 // Then this behavior is convenient for template constraint.
6048 static assert(0, T.stringof~" is not a string type");
6050 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
6052 static if (is(T : U[], U))
6053 alias StringTypeOf = U[];
6054 else
6055 static assert(0);
6057 else
6058 static assert(0, T.stringof~" is not a string type");
6061 @safe unittest
6063 import std.meta : Alias;
6064 static foreach (T; CharTypeList)
6065 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6067 static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6069 static if (!__traits(isSame, Q, InoutOf))
6071 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6073 alias Str = Q!T[];
6074 struct C(S) { S val; alias val this; }
6075 static assert(is(StringTypeOf!(C!Str) == Str));
6079 static foreach (T; CharTypeList)
6080 static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6082 static assert(!is(StringTypeOf!( Q!T[] )));
6086 @safe unittest
6088 static assert(is(StringTypeOf!(char[4]) == char[]));
6090 struct S
6092 string s;
6093 alias s this;
6096 struct T
6098 S s;
6099 alias s this;
6102 static assert(is(StringTypeOf!S == string));
6103 static assert(is(StringTypeOf!T == string));
6108 template AssocArrayTypeOf(T)
6110 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6111 alias X = AssocArrayTypeOf!AT;
6112 else
6113 alias X = OriginalType!T;
6115 static if (__traits(isAssociativeArray, X))
6117 alias AssocArrayTypeOf = X;
6119 else
6120 static assert(0, T.stringof~" is not an associative array type");
6123 @safe unittest
6125 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6126 static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6127 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6128 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6130 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) ));
6133 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6134 static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6135 static foreach (P; AliasSeq!TypeQualifierList)
6136 static foreach (Q; AliasSeq!TypeQualifierList)
6137 static foreach (R; AliasSeq!TypeQualifierList)
6139 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6145 template BuiltinTypeOf(T)
6147 static if (is(T : void))
6148 alias BuiltinTypeOf = void;
6149 else
6151 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6152 alias X = BuiltinTypeOf!AT;
6153 else
6154 alias X = OriginalType!T;
6155 static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6156 __traits(isStaticArray, X) || is(X == E[], E) ||
6157 __traits(isAssociativeArray, X) || is(X == typeof(null)))
6158 alias BuiltinTypeOf = X;
6159 else
6160 static assert(0);
6164 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6165 // isSomething
6166 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6169 * Detect whether `T` is a built-in boolean type.
6171 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6174 @safe unittest
6176 static assert( isBoolean!bool);
6177 enum EB : bool { a = true }
6178 static assert( isBoolean!EB);
6180 struct SubTypeOfBool
6182 bool val;
6183 alias val this;
6185 static assert(!isBoolean!(SubTypeOfBool));
6188 @safe unittest
6190 static struct S(T)
6192 T t;
6193 alias t this;
6195 static assert(!isIntegral!(S!bool));
6199 * Detect whether `T` is a built-in integral type. Types `bool`,
6200 * `char`, `wchar`, and `dchar` are not considered integral.
6202 template isIntegral(T)
6204 static if (!__traits(isIntegral, T))
6205 enum isIntegral = false;
6206 else static if (is(T U == enum))
6207 enum isIntegral = isIntegral!U;
6208 else
6209 enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6210 && !is(immutable T == immutable bool) && !is(T == __vector);
6214 @safe unittest
6216 static assert(
6217 isIntegral!byte &&
6218 isIntegral!short &&
6219 isIntegral!int &&
6220 isIntegral!long &&
6221 isIntegral!(const(long)) &&
6222 isIntegral!(immutable(long))
6225 static assert(
6226 !isIntegral!bool &&
6227 !isIntegral!char &&
6228 !isIntegral!double
6231 // types which act as integral values do not pass
6232 struct S
6234 int val;
6235 alias val this;
6238 static assert(!isIntegral!S);
6241 @safe unittest
6243 static foreach (T; IntegralTypeList)
6245 static foreach (Q; TypeQualifierList)
6247 static assert( isIntegral!(Q!T));
6248 static assert(!isIntegral!(SubTypeOf!(Q!T)));
6252 static assert(!isIntegral!float);
6254 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
6255 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6256 enum EI : int { a = -1, b = 0, c = 1 }
6257 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU);
6258 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI);
6262 * Detect whether `T` is a built-in floating point type.
6264 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6267 @safe unittest
6269 static assert(
6270 isFloatingPoint!float &&
6271 isFloatingPoint!double &&
6272 isFloatingPoint!real &&
6273 isFloatingPoint!(const(real)) &&
6274 isFloatingPoint!(immutable(real))
6277 static assert(!isFloatingPoint!int);
6279 // types which act as floating point values do not pass
6280 struct S
6282 float val;
6283 alias val this;
6286 static assert(!isFloatingPoint!S);
6289 @safe unittest
6291 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6293 static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6295 static foreach (Q; TypeQualifierList)
6297 static assert( isFloatingPoint!(Q!T));
6298 static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6301 static foreach (T; IntegralTypeList)
6303 static foreach (Q; TypeQualifierList)
6305 static assert(!isFloatingPoint!(Q!T));
6308 static if (is(__vector(float[4])))
6310 static assert(!isFloatingPoint!(__vector(float[4])));
6315 * Detect whether `T` is a built-in numeric type (integral or floating
6316 * point).
6318 template isNumeric(T)
6320 static if (!__traits(isArithmetic, T))
6321 enum isNumeric = false;
6322 else static if (__traits(isFloating, T))
6323 enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6324 else static if (is(T U == enum))
6325 enum isNumeric = isNumeric!U;
6326 else
6327 enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6328 && !is(immutable T == immutable bool) && !is(T == __vector);
6332 @safe unittest
6334 static assert(
6335 isNumeric!byte &&
6336 isNumeric!short &&
6337 isNumeric!int &&
6338 isNumeric!long &&
6339 isNumeric!float &&
6340 isNumeric!double &&
6341 isNumeric!real &&
6342 isNumeric!(const(real)) &&
6343 isNumeric!(immutable(real))
6346 static assert(
6347 !isNumeric!void &&
6348 !isNumeric!bool &&
6349 !isNumeric!char &&
6350 !isNumeric!wchar &&
6351 !isNumeric!dchar
6354 // types which act as numeric values do not pass
6355 struct S
6357 int val;
6358 alias val this;
6361 static assert(!isNumeric!S);
6364 @safe unittest
6366 static foreach (T; AliasSeq!(NumericTypeList))
6368 static foreach (Q; TypeQualifierList)
6370 static assert( isNumeric!(Q!T));
6371 static assert(!isNumeric!(SubTypeOf!(Q!T)));
6375 static struct S(T)
6377 T t;
6378 alias t this;
6380 static assert(!isNumeric!(S!int));
6382 enum EChar : char { a = 0, }
6383 static assert(!isNumeric!EChar);
6385 static if (is(__vector(float[4])))
6387 static assert(!isNumeric!(__vector(float[4])));
6389 static if (is(__vector(int[4])))
6391 static assert(!isNumeric!(__vector(int[4])));
6394 static assert(!isNumeric!ifloat);
6395 static assert(!isNumeric!cfloat);
6399 * Detect whether `T` is a scalar type (a built-in numeric, character or
6400 * boolean type).
6402 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6405 @safe unittest
6407 static assert(!isScalarType!void);
6408 static assert( isScalarType!(immutable(byte)));
6409 static assert( isScalarType!(immutable(ushort)));
6410 static assert( isScalarType!(immutable(int)));
6411 static assert( isScalarType!(ulong));
6412 static assert( isScalarType!(shared(float)));
6413 static assert( isScalarType!(shared(const bool)));
6414 static assert( isScalarType!(const(char)));
6415 static assert( isScalarType!(wchar));
6416 static assert( isScalarType!(const(dchar)));
6417 static assert( isScalarType!(const(double)));
6418 static assert( isScalarType!(const(real)));
6421 @safe unittest
6423 static struct S(T)
6425 T t;
6426 alias t this;
6428 static assert(!isScalarType!(S!int));
6432 * Detect whether `T` is a basic type (scalar type or void).
6434 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6437 @safe unittest
6439 static assert(isBasicType!void);
6440 static assert(isBasicType!(const(void)));
6441 static assert(isBasicType!(shared(void)));
6442 static assert(isBasicType!(immutable(void)));
6443 static assert(isBasicType!(shared const(void)));
6444 static assert(isBasicType!(shared inout(void)));
6445 static assert(isBasicType!(shared inout const(void)));
6446 static assert(isBasicType!(inout(void)));
6447 static assert(isBasicType!(inout const(void)));
6448 static assert(isBasicType!(immutable(int)));
6449 static assert(isBasicType!(shared(float)));
6450 static assert(isBasicType!(shared(const bool)));
6451 static assert(isBasicType!(const(dchar)));
6455 * Detect whether `T` is a built-in unsigned numeric type.
6457 template isUnsigned(T)
6459 static if (!__traits(isUnsigned, T))
6460 enum isUnsigned = false;
6461 else static if (is(T U == enum))
6462 enum isUnsigned = isUnsigned!U;
6463 else
6464 enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6465 && !is(immutable T == immutable bool) && !is(T == __vector);
6469 @safe unittest
6471 static assert(
6472 isUnsigned!uint &&
6473 isUnsigned!ulong
6476 static assert(
6477 !isUnsigned!char &&
6478 !isUnsigned!int &&
6479 !isUnsigned!long &&
6480 !isUnsigned!char &&
6481 !isUnsigned!wchar &&
6482 !isUnsigned!dchar
6486 @safe unittest
6488 static foreach (T; AliasSeq!(UnsignedIntTypeList))
6490 static foreach (Q; TypeQualifierList)
6492 static assert( isUnsigned!(Q!T));
6493 static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6497 static struct S(T)
6499 T t;
6500 alias t this;
6502 static assert(!isUnsigned!(S!uint));
6504 enum EChar : char { a = 0, }
6505 static assert(!isUnsigned!EChar);
6507 static if (is(__vector(uint[4])))
6509 static assert(!isUnsigned!(__vector(uint[4])));
6514 * Detect whether `T` is a built-in signed numeric type.
6516 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6517 && is(T : real);
6520 @safe unittest
6522 static assert(
6523 isSigned!int &&
6524 isSigned!long
6527 static assert(
6528 !isSigned!uint &&
6529 !isSigned!ulong
6533 @safe unittest
6535 enum E { e1 = 0 }
6536 static assert(isSigned!E);
6538 enum Eubyte : ubyte { e1 = 0 }
6539 static assert(!isSigned!Eubyte);
6541 static foreach (T; AliasSeq!(SignedIntTypeList))
6543 static foreach (Q; TypeQualifierList)
6545 static assert( isSigned!(Q!T));
6546 static assert(!isSigned!(SubTypeOf!(Q!T)));
6550 static struct S(T)
6552 T t;
6553 alias t this;
6555 static assert(!isSigned!(S!uint));
6557 static if (is(__vector(int[4])))
6559 static assert(!isSigned!(__vector(int[4])));
6562 static assert(!isSigned!ifloat);
6563 static assert(!isSigned!cfloat);
6566 // https://issues.dlang.org/show_bug.cgi?id=17196
6567 @safe unittest
6569 static assert(isUnsigned!bool == false);
6570 static assert(isSigned!bool == false);
6574 * Detect whether `T` is one of the built-in character types.
6576 * The built-in char types are any of `char`, `wchar` or `dchar`, with
6577 * or without qualifiers.
6579 template isSomeChar(T)
6581 static if (!__traits(isUnsigned, T))
6582 enum isSomeChar = false;
6583 else static if (is(T U == enum))
6584 enum isSomeChar = isSomeChar!U;
6585 else
6586 enum isSomeChar = !__traits(isZeroInit, T);
6590 @safe unittest
6592 //Char types
6593 static assert( isSomeChar!char);
6594 static assert( isSomeChar!wchar);
6595 static assert( isSomeChar!dchar);
6596 static assert( isSomeChar!(typeof('c')));
6597 static assert( isSomeChar!(immutable char));
6598 static assert( isSomeChar!(const dchar));
6600 //Non char types
6601 static assert(!isSomeChar!int);
6602 static assert(!isSomeChar!byte);
6603 static assert(!isSomeChar!string);
6604 static assert(!isSomeChar!wstring);
6605 static assert(!isSomeChar!dstring);
6606 static assert(!isSomeChar!(char[4]));
6609 @safe unittest
6611 enum EC : char { a = 'x', b = 'y' }
6613 static foreach (T; AliasSeq!(CharTypeList, EC))
6615 static foreach (Q; TypeQualifierList)
6617 static assert( isSomeChar!( Q!T ));
6618 static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6622 // alias-this types are not allowed
6623 static struct S(T)
6625 T t;
6626 alias t this;
6628 static assert(!isSomeChar!(S!char));
6632 Detect whether `T` is one of the built-in string types.
6634 The built-in string types are `Char[]`, where `Char` is any of `char`,
6635 `wchar` or `dchar`, with or without qualifiers.
6637 Static arrays of characters (like `char[80]`) are not considered
6638 built-in string types.
6640 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6643 @safe unittest
6645 //String types
6646 static assert( isSomeString!string);
6647 static assert( isSomeString!(wchar[]));
6648 static assert( isSomeString!(dchar[]));
6649 static assert( isSomeString!(typeof("aaa")));
6650 static assert( isSomeString!(const(char)[]));
6652 //Non string types
6653 static assert(!isSomeString!int);
6654 static assert(!isSomeString!(int[]));
6655 static assert(!isSomeString!(byte[]));
6656 static assert(!isSomeString!(typeof(null)));
6657 static assert(!isSomeString!(char[4]));
6659 enum ES : string { a = "aaa", b = "bbb" }
6660 static assert(!isSomeString!ES);
6662 static struct Stringish
6664 string str;
6665 alias str this;
6667 static assert(!isSomeString!Stringish);
6670 @safe unittest
6672 static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6674 static assert( isSomeString!( T ));
6675 static assert(!isSomeString!(SubTypeOf!(T)));
6677 enum C : char { _ = 0 }
6678 static assert(!isSomeString!(C[]));
6682 * Detect whether type `T` is a narrow string.
6684 * All arrays that use char, wchar, and their qualified versions are narrow
6685 * strings. (Those include string and wstring).
6687 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6690 @safe unittest
6692 static assert(isNarrowString!string);
6693 static assert(isNarrowString!wstring);
6694 static assert(isNarrowString!(char[]));
6695 static assert(isNarrowString!(wchar[]));
6697 static assert(!isNarrowString!dstring);
6698 static assert(!isNarrowString!(dchar[]));
6700 static assert(!isNarrowString!(typeof(null)));
6701 static assert(!isNarrowString!(char[4]));
6703 enum ES : string { a = "aaa", b = "bbb" }
6704 static assert(!isNarrowString!ES);
6706 static struct Stringish
6708 string str;
6709 alias str this;
6711 static assert(!isNarrowString!Stringish);
6714 @safe unittest
6716 import std.meta : Alias;
6717 static foreach (T; AliasSeq!(char[], string, wstring))
6719 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6721 static assert( isNarrowString!( Q!T ));
6722 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6726 static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6728 static foreach (Q; TypeQualifierList)
6730 static assert(!isNarrowString!( Q!T ));
6731 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6734 enum C : char { _ = 0 }
6735 static assert(!isNarrowString!(C[]));
6739 * Detects whether `T` is a comparable type. Basic types and structs and
6740 * classes that implement opCmp are ordering comparable.
6742 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6745 @safe unittest
6747 static assert(isOrderingComparable!int);
6748 static assert(isOrderingComparable!string);
6750 static struct Foo {}
6751 static assert(!isOrderingComparable!Foo);
6753 static struct Bar
6755 int a;
6756 auto opCmp(Bar b1) const { return a - b1.a; }
6759 Bar b1 = Bar(5);
6760 Bar b2 = Bar(7);
6761 assert(isOrderingComparable!Bar && b2 > b1);
6764 /// ditto
6765 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6767 @safe unittest
6769 static assert(isEqualityComparable!int);
6770 static assert(isEqualityComparable!string);
6771 static assert(!isEqualityComparable!void);
6773 struct Foo {}
6774 static assert(isEqualityComparable!Foo);
6776 struct Bar
6778 int a;
6779 auto opEquals(Bar b1) const { return a == b1.a; }
6782 Bar b1 = Bar(5);
6783 Bar b2 = Bar(5);
6784 Bar b3 = Bar(7);
6785 static assert(isEqualityComparable!Bar);
6786 assert(b1 == b2);
6787 assert(b1 != b3);
6791 $(RED Warning: This trait will be deprecated as soon as it is no longer used
6792 in Phobos. For a function parameter to safely accept a type
6793 that implicitly converts to string as a string, the conversion
6794 needs to happen at the callsite; otherwise, the conversion is
6795 done inside the function, and in many cases, that means that
6796 local memory is sliced (e.g. if a static array is passed to
6797 the function, then it's copied, and the resulting dynamic
6798 array will be a slice of a local variable). So, if the
6799 resulting string escapes the function, the string refers to
6800 invalid memory, and accessing it would mean accessing invalid
6801 memory. As such, the only safe way for a function to accept
6802 types that implicitly convert to string is for the implicit
6803 conversion to be done at the callsite, and that can only occur
6804 if the parameter is explicitly typed as an array, whereas
6805 using isConvertibleToString in a template constraint would
6806 result in the conversion being done inside the function. As
6807 such, isConvertibleToString is inherently unsafe and is going
6808 to be deprecated.)
6810 Detect whether `T` is a struct, static array, or enum that is implicitly
6811 convertible to a string.
6813 template isConvertibleToString(T)
6815 enum isConvertibleToString =
6816 (isAggregateType!T || isStaticArray!T || is(T == enum))
6817 && is(StringTypeOf!T);
6821 @safe unittest
6823 static struct AliasedString
6825 string s;
6826 alias s this;
6829 enum StringEnum { a = "foo" }
6831 assert(!isConvertibleToString!string);
6832 assert(isConvertibleToString!AliasedString);
6833 assert(isConvertibleToString!StringEnum);
6834 assert(isConvertibleToString!(char[25]));
6835 assert(!isConvertibleToString!(char[]));
6838 // https://issues.dlang.org/show_bug.cgi?id=16573
6839 @safe unittest
6841 enum I : int { foo = 1 }
6842 enum S : string { foo = "foo" }
6843 assert(!isConvertibleToString!I);
6844 assert(isConvertibleToString!S);
6847 package template convertToString(T)
6849 static if (isConvertibleToString!T)
6850 alias convertToString = StringTypeOf!T;
6851 else
6852 alias convertToString = T;
6856 * Detect whether type `T` is a string that will be autodecoded.
6858 * Given a type `S` that is one of:
6859 * $(OL
6860 * $(LI `const(char)[]`)
6861 * $(LI `const(wchar)[]`)
6863 * Type `T` can be one of:
6864 * $(OL
6865 * $(LI `S`)
6866 * $(LI implicitly convertible to `T`)
6867 * $(LI an enum with a base type `T`)
6868 * $(LI an aggregate with a base type `T`)
6870 * with the proviso that `T` cannot be a static array.
6872 * Params:
6873 * T = type to be tested
6875 * Returns:
6876 * true if T represents a string that is subject to autodecoding
6878 * See Also:
6879 * $(LREF isNarrowString)
6881 template isAutodecodableString(T)
6883 import std.range.primitives : autodecodeStrings;
6885 enum isAutodecodableString = autodecodeStrings &&
6886 (is(T : const char[]) || is(T : const wchar[]))
6887 && !is(T : U[n], U, size_t n)
6888 && !is(immutable T : immutable noreturn[]);
6892 @safe unittest
6894 static struct Stringish
6896 string s;
6897 alias s this;
6899 static assert(isAutodecodableString!wstring);
6900 static assert(isAutodecodableString!Stringish);
6901 static assert(!isAutodecodableString!dstring);
6903 enum E : const(char)[3] { X = "abc" }
6904 enum F : const(char)[] { X = "abc" }
6905 enum G : F { X = F.init }
6907 static assert(isAutodecodableString!(char[]));
6908 static assert(!isAutodecodableString!(E));
6909 static assert(isAutodecodableString!(F));
6910 static assert(isAutodecodableString!(G));
6912 struct Stringish2
6914 Stringish s;
6915 alias s this;
6918 enum H : Stringish { X = Stringish() }
6919 enum I : Stringish2 { X = Stringish2() }
6921 static assert(isAutodecodableString!(H));
6922 static assert(isAutodecodableString!(I));
6924 static assert(!isAutodecodableString!(noreturn[]));
6925 static assert(!isAutodecodableString!(immutable(noreturn)[]));
6929 * Detect whether type `T` is a static array.
6931 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6934 @safe unittest
6936 static assert( isStaticArray!(int[3]));
6937 static assert( isStaticArray!(const(int)[5]));
6938 static assert( isStaticArray!(const(int)[][5]));
6940 static assert(!isStaticArray!(const(int)[]));
6941 static assert(!isStaticArray!(immutable(int)[]));
6942 static assert(!isStaticArray!(const(int)[4][]));
6943 static assert(!isStaticArray!(int[]));
6944 static assert(!isStaticArray!(int[char]));
6945 static assert(!isStaticArray!(int[1][]));
6946 static assert(!isStaticArray!(int[int]));
6947 static assert(!isStaticArray!int);
6950 @safe unittest
6952 static foreach (T; AliasSeq!(int[51], int[][2],
6953 char[][int][11], immutable char[13u],
6954 const(real)[1], const(real)[1][1], void[0]))
6956 static foreach (Q; TypeQualifierList)
6958 static assert( isStaticArray!( Q!T ));
6959 static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
6963 //enum ESA : int[1] { a = [1], b = [2] }
6964 //static assert( isStaticArray!ESA);
6968 * Detect whether type `T` is a dynamic array.
6970 template isDynamicArray(T)
6972 static if (is(T == U[], U))
6973 enum bool isDynamicArray = true;
6974 else static if (is(T U == enum))
6975 // BUG: isDynamicArray / isStaticArray considers enums
6976 // with appropriate base types as dynamic/static arrays
6977 // Retain old behaviour for now, see
6978 // https://github.com/dlang/phobos/pull/7574
6979 enum bool isDynamicArray = isDynamicArray!U;
6980 else
6981 enum bool isDynamicArray = false;
6985 @safe unittest
6987 static assert( isDynamicArray!(int[]));
6988 static assert( isDynamicArray!(string));
6989 static assert( isDynamicArray!(long[3][]));
6991 static assert(!isDynamicArray!(int[5]));
6992 static assert(!isDynamicArray!(typeof(null)));
6995 @safe unittest
6997 import std.meta : AliasSeq;
6998 static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
7000 static foreach (Q; TypeQualifierList)
7002 static assert( isDynamicArray!( Q!T ));
7003 static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
7007 static assert(!isDynamicArray!(int[5]));
7009 static struct AliasThis
7011 int[] values;
7012 alias values this;
7015 static assert(!isDynamicArray!AliasThis);
7017 // https://github.com/dlang/phobos/pull/7574/files#r464115492
7018 enum E : string
7020 a = "a",
7021 b = "b",
7023 static assert( isDynamicArray!E);
7027 * Detect whether type `T` is an array (static or dynamic; for associative
7028 * arrays see $(LREF isAssociativeArray)).
7030 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
7033 @safe unittest
7035 static assert( isArray!(int[]));
7036 static assert( isArray!(int[5]));
7037 static assert( isArray!(string));
7039 static assert(!isArray!uint);
7040 static assert(!isArray!(uint[uint]));
7041 static assert(!isArray!(typeof(null)));
7044 @safe unittest
7046 import std.meta : AliasSeq;
7047 static foreach (T; AliasSeq!(int[], int[5], void[]))
7049 static foreach (Q; TypeQualifierList)
7051 static assert( isArray!(Q!T));
7052 static assert(!isArray!(SubTypeOf!(Q!T)));
7058 * Detect whether `T` is an associative array type
7060 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
7063 @safe unittest
7065 struct S;
7067 static assert( isAssociativeArray!(int[string]));
7068 static assert( isAssociativeArray!(S[S]));
7069 static assert(!isAssociativeArray!(string[]));
7070 static assert(!isAssociativeArray!S);
7071 static assert(!isAssociativeArray!(int[4]));
7074 @safe unittest
7076 struct Foo
7078 @property uint[] keys() { return null; }
7079 @property uint[] values() { return null; }
7082 static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7084 static foreach (Q; TypeQualifierList)
7086 static assert( isAssociativeArray!(Q!T));
7087 static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7091 static assert(!isAssociativeArray!Foo);
7092 static assert(!isAssociativeArray!int);
7093 static assert(!isAssociativeArray!(int[]));
7094 static assert(!isAssociativeArray!(typeof(null)));
7096 //enum EAA : int[int] { a = [1:1], b = [2:2] }
7097 //static assert( isAssociativeArray!EAA);
7101 * Detect whether type `T` is a builtin type.
7103 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7106 @safe unittest
7108 class C;
7109 union U;
7110 struct S;
7111 interface I;
7113 static assert( isBuiltinType!void);
7114 static assert( isBuiltinType!string);
7115 static assert( isBuiltinType!(int[]));
7116 static assert( isBuiltinType!(C[string]));
7117 static assert( isBuiltinType!(typeof(null)));
7118 static assert(!isBuiltinType!C);
7119 static assert(!isBuiltinType!U);
7120 static assert(!isBuiltinType!S);
7121 static assert(!isBuiltinType!I);
7122 static assert(!isBuiltinType!(void delegate(int)));
7126 * Detect whether type `T` is a SIMD vector type.
7128 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7131 @safe unittest
7133 static if (is(__vector(float[4])))
7135 alias SimdVec = __vector(float[4]);
7136 static assert(isSIMDVector!(__vector(float[4])));
7137 static assert(isSIMDVector!SimdVec);
7139 static assert(!isSIMDVector!uint);
7140 static assert(!isSIMDVector!(float[4]));
7144 * Detect whether type `T` is a pointer.
7146 enum bool isPointer(T) = is(T == U*, U);
7149 @safe unittest
7151 void fun();
7153 static assert( isPointer!(int*));
7154 static assert( isPointer!(int function()));
7155 static assert(!isPointer!int);
7156 static assert(!isPointer!string);
7157 static assert(!isPointer!(typeof(null)));
7158 static assert(!isPointer!(typeof(fun)));
7159 static assert(!isPointer!(int delegate()));
7162 @safe unittest
7164 static foreach (T; AliasSeq!(int*, void*, char[]*))
7166 static foreach (Q; TypeQualifierList)
7168 static assert( isPointer!(Q!T));
7169 static assert(!isPointer!(SubTypeOf!(Q!T)));
7173 static assert(!isPointer!uint);
7174 static assert(!isPointer!(uint[uint]));
7175 static assert(!isPointer!(char[]));
7176 static assert(!isPointer!(typeof(null)));
7180 Returns the target type of a pointer.
7182 alias PointerTarget(T : T*) = T;
7185 @safe unittest
7187 static assert(is(PointerTarget!(int*) == int));
7188 static assert(is(PointerTarget!(void*) == void));
7192 * Detect whether type `T` is an aggregate type.
7194 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
7195 is(T == class) || is(T == interface);
7198 @safe unittest
7200 class C;
7201 union U;
7202 struct S;
7203 interface I;
7205 static assert( isAggregateType!C);
7206 static assert( isAggregateType!U);
7207 static assert( isAggregateType!S);
7208 static assert( isAggregateType!I);
7209 static assert(!isAggregateType!void);
7210 static assert(!isAggregateType!string);
7211 static assert(!isAggregateType!(int[]));
7212 static assert(!isAggregateType!(C[string]));
7213 static assert(!isAggregateType!(void delegate(int)));
7217 * Returns `true` if T can be iterated over using a `foreach` loop with
7218 * a single loop variable of automatically inferred type, regardless of how
7219 * the `foreach` loop is implemented. This includes ranges, structs/classes
7220 * that define `opApply` with a single loop variable, and builtin dynamic,
7221 * static and associative arrays.
7223 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7226 @safe unittest
7228 struct OpApply
7230 int opApply(scope int delegate(ref uint) dg) { assert(0); }
7233 struct Range
7235 @property uint front() { assert(0); }
7236 void popFront() { assert(0); }
7237 enum bool empty = false;
7240 static assert( isIterable!(uint[]));
7241 static assert( isIterable!OpApply);
7242 static assert( isIterable!(uint[string]));
7243 static assert( isIterable!Range);
7245 static assert(!isIterable!uint);
7249 * Returns true if T is not const or immutable. Note that isMutable is true for
7250 * string, or immutable(char)[], because the 'head' is mutable.
7252 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7255 @safe unittest
7257 static assert( isMutable!int);
7258 static assert( isMutable!string);
7259 static assert( isMutable!(shared int));
7260 static assert( isMutable!(shared const(int)[]));
7262 static assert(!isMutable!(const int));
7263 static assert(!isMutable!(inout int));
7264 static assert(!isMutable!(shared(const int)));
7265 static assert(!isMutable!(shared(inout int)));
7266 static assert(!isMutable!(immutable string));
7270 * Returns true if T is an instance of the template S.
7272 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7273 /// ditto
7274 template isInstanceOf(alias S, alias T)
7276 enum impl(alias T : S!Args, Args...) = true;
7277 enum impl(alias T) = false;
7278 enum isInstanceOf = impl!T;
7282 @safe unittest
7284 static struct Foo(T...) { }
7285 static struct Bar(T...) { }
7286 static struct Doo(T) { }
7287 static struct ABC(int x) { }
7288 static void fun(T)() { }
7289 template templ(T) { }
7291 static assert(isInstanceOf!(Foo, Foo!int));
7292 static assert(!isInstanceOf!(Foo, Bar!int));
7293 static assert(!isInstanceOf!(Foo, int));
7294 static assert(isInstanceOf!(Doo, Doo!int));
7295 static assert(isInstanceOf!(ABC, ABC!1));
7296 static assert(!isInstanceOf!(Foo, Foo));
7297 static assert(isInstanceOf!(fun, fun!int));
7298 static assert(isInstanceOf!(templ, templ!int));
7302 * To use `isInstanceOf` to check the identity of a template while inside of said
7303 * template, use $(LREF TemplateOf).
7305 @safe unittest
7307 static struct A(T = void)
7309 // doesn't work as expected, only accepts A when T = void
7310 void func(B)(B b) if (isInstanceOf!(A, B)) {}
7312 // correct behavior
7313 void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {}
7316 A!(void) a1;
7317 A!(void) a2;
7318 A!(int) a3;
7320 static assert(!__traits(compiles, a1.func(a3)));
7321 static assert( __traits(compiles, a1.method(a2)));
7322 static assert( __traits(compiles, a1.method(a3)));
7325 @safe unittest
7327 static void fun1(T)() { }
7328 static void fun2(T)() { }
7329 template templ1(T) { }
7330 template templ2(T) { }
7332 static assert(!isInstanceOf!(fun1, fun2!int));
7333 static assert(!isInstanceOf!(templ1, templ2!int));
7337 * Check whether the tuple T is an expression tuple.
7338 * An expression tuple only contains expressions.
7340 * See_Also: $(LREF isTypeTuple).
7342 template isExpressions(T...)
7344 static foreach (Ti; T)
7346 static if (!is(typeof(isExpressions) == bool) && // not yet defined
7347 (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7349 enum isExpressions = false;
7352 static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7354 enum isExpressions = true;
7359 @safe unittest
7361 static assert(isExpressions!(1, 2.0, "a"));
7362 static assert(!isExpressions!(int, double, string));
7363 static assert(!isExpressions!(int, 2.0, "a"));
7367 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7370 alias isExpressionTuple = isExpressions;
7372 @safe unittest
7374 void foo();
7375 static int bar() { return 42; }
7376 immutable aa = [ 1: -1 ];
7377 alias myint = int;
7379 static assert( isExpressionTuple!(42));
7380 static assert( isExpressionTuple!aa);
7381 static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7382 static assert( isExpressionTuple!(bar()));
7384 static assert(!isExpressionTuple!isExpressionTuple);
7385 static assert(!isExpressionTuple!foo);
7386 static assert(!isExpressionTuple!( (a) { } ));
7387 static assert(!isExpressionTuple!int);
7388 static assert(!isExpressionTuple!myint);
7393 * Check whether the tuple `T` is a type tuple.
7394 * A type tuple only contains types.
7396 * See_Also: $(LREF isExpressions).
7398 enum isTypeTuple(T...) =
7400 static foreach (U; T)
7401 static if (!is(U))
7402 if (__ctfe)
7403 return false;
7404 return true;
7405 }();
7408 @safe unittest
7410 static assert(isTypeTuple!(int, float, string));
7411 static assert(!isTypeTuple!(1, 2.0, "a"));
7412 static assert(!isTypeTuple!(1, double, string));
7415 @safe unittest
7417 class C {}
7418 void func(int) {}
7419 auto c = new C;
7420 enum CONST = 42;
7422 static assert( isTypeTuple!int);
7423 static assert( isTypeTuple!string);
7424 static assert( isTypeTuple!C);
7425 static assert( isTypeTuple!(typeof(func)));
7426 static assert( isTypeTuple!(int, char, double));
7428 static assert(!isTypeTuple!c);
7429 static assert(!isTypeTuple!isTypeTuple);
7430 static assert(!isTypeTuple!CONST);
7435 Detect whether symbol or type `T` is a function pointer.
7437 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7440 @safe unittest
7442 static void foo() {}
7443 void bar() {}
7445 auto fpfoo = &foo;
7446 static assert( isFunctionPointer!fpfoo);
7447 static assert( isFunctionPointer!(void function()));
7449 auto dgbar = &bar;
7450 static assert(!isFunctionPointer!dgbar);
7451 static assert(!isFunctionPointer!(void delegate()));
7452 static assert(!isFunctionPointer!foo);
7453 static assert(!isFunctionPointer!bar);
7455 static assert( isFunctionPointer!((int a) {}));
7459 Detect whether symbol or type `T` is a delegate.
7461 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7464 @safe unittest
7466 static void sfunc() { }
7467 int x;
7468 void func() { x++; }
7470 int delegate() dg;
7471 assert(isDelegate!dg);
7472 assert(isDelegate!(int delegate()));
7473 assert(isDelegate!(typeof(&func)));
7475 int function() fp;
7476 assert(!isDelegate!fp);
7477 assert(!isDelegate!(int function()));
7478 assert(!isDelegate!(typeof(&sfunc)));
7482 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7484 Params:
7485 T = The type to check
7486 Returns:
7487 A `bool`
7489 enum bool isSomeFunction(alias T) =
7490 is(T == return) ||
7491 is(typeof(T) == return) ||
7492 is(typeof(&T) == return); // @property
7495 @safe unittest
7497 static real func(ref int) { return 0; }
7498 static void prop() @property { }
7499 class C
7501 real method(ref int) { return 0; }
7502 real prop() @property { return 0; }
7504 auto c = new C;
7505 auto fp = &func;
7506 auto dg = &c.method;
7508 static assert( isSomeFunction!func);
7509 static assert( isSomeFunction!prop);
7510 static assert( isSomeFunction!(C.method));
7511 static assert( isSomeFunction!(C.prop));
7512 static assert( isSomeFunction!(c.prop));
7513 static assert( isSomeFunction!fp);
7514 static assert( isSomeFunction!dg);
7516 real val;
7517 static assert(!isSomeFunction!int);
7518 static assert(!isSomeFunction!val);
7521 @safe unittest
7523 void nestedFunc() { }
7524 void nestedProp() @property { }
7525 static assert(isSomeFunction!nestedFunc);
7526 static assert(isSomeFunction!nestedProp);
7527 static assert(isSomeFunction!(real function(ref int)));
7528 static assert(isSomeFunction!(real delegate(ref int)));
7529 static assert(isSomeFunction!((int a) { return a; }));
7530 static assert(!isSomeFunction!isSomeFunction);
7534 Detect whether `T` is a callable object, which can be called with the
7535 function call operator `$(LPAREN)...$(RPAREN)`.
7537 template isCallable(alias callable)
7539 static if (is(typeof(&callable.opCall) == delegate))
7540 // T is a object which has a member function opCall().
7541 enum bool isCallable = true;
7542 else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7543 // T is a type which has a static member function opCall().
7544 enum bool isCallable = true;
7545 else static if (is(typeof(&callable.opCall!())))
7547 alias TemplateInstanceType = typeof(&callable.opCall!());
7548 enum bool isCallable = isCallable!TemplateInstanceType;
7550 else static if (is(typeof(&callable!())))
7552 alias TemplateInstanceType = typeof(&callable!());
7553 enum bool isCallable = isCallable!TemplateInstanceType;
7555 else
7557 enum bool isCallable = isSomeFunction!callable;
7561 /// Functions, lambdas, and aggregate types with (static) opCall.
7562 @safe unittest
7564 void f() { }
7565 int g(int x) { return x; }
7567 static assert( isCallable!f);
7568 static assert( isCallable!g);
7570 class C { int opCall(int) { return 0; } }
7571 auto c = new C;
7572 struct S { static int opCall(int) { return 0; } }
7573 interface I { real value() @property; }
7575 static assert( isCallable!c);
7576 static assert( isCallable!(c.opCall));
7577 static assert( isCallable!S);
7578 static assert( isCallable!(I.value));
7579 static assert( isCallable!((int a) { return a; }));
7581 static assert(!isCallable!I);
7584 /// Templates
7585 @safe unittest
7587 void f()() { }
7588 T g(T = int)(T x) { return x; }
7589 struct S1 { static void opCall()() { } }
7590 struct S2 { static T opCall(T = int)(T x) {return x; } }
7592 static assert( isCallable!f);
7593 static assert( isCallable!g);
7594 static assert( isCallable!S1);
7595 static assert( isCallable!S2);
7598 /// Overloaded functions and function templates.
7599 @safe unittest
7601 static struct Wrapper
7603 void f() { }
7604 int f(int x) { return x; }
7606 void g()() { }
7607 T g(T = int)(T x) { return x; }
7610 static assert(isCallable!(Wrapper.f));
7611 static assert(isCallable!(Wrapper.g));
7616 Detect whether `T` is an abstract function.
7618 Params:
7619 T = The type to check
7620 Returns:
7621 A `bool`
7623 enum isAbstractFunction(alias T) = __traits(isAbstractFunction, T);
7626 @safe unittest
7628 struct S { void foo() { } }
7629 class C { void foo() { } }
7630 class AC { abstract void foo(); }
7631 static assert(!isAbstractFunction!(int));
7632 static assert(!isAbstractFunction!(S.foo));
7633 static assert(!isAbstractFunction!(C.foo));
7634 static assert( isAbstractFunction!(AC.foo));
7638 * Detect whether `T` is a final function.
7640 enum isFinalFunction(alias T) = __traits(isFinalFunction, T);
7643 @safe unittest
7645 struct S { void bar() { } }
7646 final class FC { void foo(); }
7647 class C
7649 void bar() { }
7650 final void foo();
7652 static assert(!isFinalFunction!(int));
7653 static assert(!isFinalFunction!(S.bar));
7654 static assert( isFinalFunction!(FC.foo));
7655 static assert(!isFinalFunction!(C.bar));
7656 static assert( isFinalFunction!(C.foo));
7660 Determines if `f` is a function that requires a context pointer.
7662 Params:
7663 f = The type to check
7664 Returns
7665 A `bool`
7667 template isNestedFunction(alias f)
7669 enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7673 @safe unittest
7675 static void f() {}
7676 static void fun()
7678 int i;
7679 int f() { return i; }
7681 static assert(isNestedFunction!(f));
7684 static assert(!isNestedFunction!f);
7687 // https://issues.dlang.org/show_bug.cgi?id=18669
7688 @safe unittest
7690 static class Outer
7692 class Inner
7696 int i;
7697 struct SS
7699 int bar() { return i; }
7701 static assert(!isNestedFunction!(Outer.Inner));
7702 static assert(!isNestedFunction!(SS));
7706 * Detect whether `T` is an abstract class.
7708 enum isAbstractClass(alias T) = __traits(isAbstractClass, T);
7711 @safe unittest
7713 struct S { }
7714 class C { }
7715 abstract class AC { }
7716 static assert(!isAbstractClass!S);
7717 static assert(!isAbstractClass!C);
7718 static assert( isAbstractClass!AC);
7719 C c;
7720 static assert(!isAbstractClass!c);
7721 AC ac;
7722 static assert( isAbstractClass!ac);
7726 * Detect whether `T` is a final class.
7728 enum isFinalClass(alias T) = __traits(isFinalClass, T);
7731 @safe unittest
7733 class C { }
7734 abstract class AC { }
7735 final class FC1 : C { }
7736 final class FC2 { }
7737 static assert(!isFinalClass!C);
7738 static assert(!isFinalClass!AC);
7739 static assert( isFinalClass!FC1);
7740 static assert( isFinalClass!FC2);
7741 C c;
7742 static assert(!isFinalClass!c);
7743 FC1 fc1;
7744 static assert( isFinalClass!fc1);
7747 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7748 // General Types
7749 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7751 version (StdDdoc)
7754 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7756 template Unconst(T)
7758 import core.internal.traits : CoreUnconst = Unconst;
7759 alias Unconst = CoreUnconst!(T);
7762 else
7764 import core.internal.traits : CoreUnconst = Unconst;
7765 alias Unconst = CoreUnconst;
7769 @safe unittest
7771 static assert(is(Unconst!int == int));
7772 static assert(is(Unconst!(const int) == int));
7773 static assert(is(Unconst!(immutable int) == int));
7774 static assert(is(Unconst!(shared int) == shared int));
7775 static assert(is(Unconst!(shared(const int)) == shared int));
7778 @safe unittest
7780 static assert(is(Unconst!( int) == int));
7781 static assert(is(Unconst!( const int) == int));
7782 static assert(is(Unconst!( inout int) == int));
7783 static assert(is(Unconst!( inout const int) == int));
7784 static assert(is(Unconst!(shared int) == shared int));
7785 static assert(is(Unconst!(shared const int) == shared int));
7786 static assert(is(Unconst!(shared inout int) == shared int));
7787 static assert(is(Unconst!(shared inout const int) == shared int));
7788 static assert(is(Unconst!( immutable int) == int));
7790 alias ImmIntArr = immutable(int[]);
7791 static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7794 version (StdDdoc)
7797 Removes all qualifiers, if any, from type `T`.
7799 template Unqual(T)
7801 import core.internal.traits : CoreUnqual = Unqual;
7802 alias Unqual = CoreUnqual!(T);
7805 else
7807 import core.internal.traits : CoreUnqual = Unqual;
7808 alias Unqual = CoreUnqual;
7812 @safe unittest
7814 static assert(is(Unqual!int == int));
7815 static assert(is(Unqual!(const int) == int));
7816 static assert(is(Unqual!(immutable int) == int));
7817 static assert(is(Unqual!(shared int) == int));
7818 static assert(is(Unqual!(shared(const int)) == int));
7821 @safe unittest
7823 static assert(is(Unqual!( int) == int));
7824 static assert(is(Unqual!( const int) == int));
7825 static assert(is(Unqual!( inout int) == int));
7826 static assert(is(Unqual!( inout const int) == int));
7827 static assert(is(Unqual!(shared int) == int));
7828 static assert(is(Unqual!(shared const int) == int));
7829 static assert(is(Unqual!(shared inout int) == int));
7830 static assert(is(Unqual!(shared inout const int) == int));
7831 static assert(is(Unqual!( immutable int) == int));
7833 alias ImmIntArr = immutable(int[]);
7834 static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7837 // [For internal use]
7838 package template ModifyTypePreservingTQ(alias Modifier, T)
7840 import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7841 alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7845 * Copies type qualifiers from `FromType` to `ToType`.
7847 * Supported type qualifiers:
7848 * $(UL
7849 * $(LI `const`)
7850 * $(LI `inout`)
7851 * $(LI `immutable`)
7852 * $(LI `shared`)
7855 template CopyTypeQualifiers(FromType, ToType)
7857 alias T(U) = ToType;
7858 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7862 @safe unittest
7864 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7867 @safe unittest
7869 static assert(is(CopyTypeQualifiers!( real, int) == int));
7870 static assert(is(CopyTypeQualifiers!( const real, int) == const int));
7871 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int));
7872 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int));
7873 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int));
7874 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int));
7875 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int));
7876 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
7877 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int));
7881 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
7882 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
7883 returned type will be the same as `ToType`.
7885 template CopyConstness(FromType, ToType)
7887 alias Unshared(T) = T;
7888 alias Unshared(T: shared U, U) = U;
7890 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
7894 @safe unittest
7896 const(int) i;
7897 CopyConstness!(typeof(i), float) f;
7898 assert( is(typeof(f) == const float));
7900 CopyConstness!(char, uint) u;
7901 assert( is(typeof(u) == uint));
7903 //The 'shared' qualifier will not be copied
7904 assert(!is(CopyConstness!(shared bool, int) == shared int));
7906 //But the constness will be
7907 assert( is(CopyConstness!(shared const real, double) == const double));
7909 //Careful, const(int)[] is a mutable array of const(int)
7910 alias MutT = CopyConstness!(const(int)[], int);
7911 assert(!is(MutT == const(int)));
7913 //Okay, const(int[]) applies to array and contained ints
7914 alias CstT = CopyConstness!(const(int[]), int);
7915 assert( is(CstT == const(int)));
7918 @safe unittest
7920 struct Test
7922 void method1() {}
7923 void method2() const {}
7924 void method3() immutable {}
7927 assert(is(CopyConstness!(typeof(Test.method1), real) == real));
7929 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
7931 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
7934 @safe unittest
7936 assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
7937 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
7940 @safe unittest
7942 static assert(is(CopyConstness!( int, real) == real));
7943 static assert(is(CopyConstness!(const int, real) == const real));
7944 static assert(is(CopyConstness!(inout int, real) == inout real));
7945 static assert(is(CopyConstness!(inout const int, real) == inout const real));
7946 static assert(is(CopyConstness!(shared int, real) == real));
7947 static assert(is(CopyConstness!(shared const int, real) == const real));
7948 static assert(is(CopyConstness!(shared inout int, real) == inout real));
7949 static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
7950 static assert(is(CopyConstness!(immutable int, real) == immutable real));
7954 Returns the inferred type of the loop variable when a variable of type T
7955 is iterated over using a `foreach` loop with a single loop variable and
7956 automatically inferred return type. Note that this may not be the same as
7957 `std.range.ElementType!Range` in the case of narrow strings, or if T
7958 has both opApply and a range interface.
7960 template ForeachType(T)
7962 alias ForeachType = typeof(
7963 (inout int x = 0)
7965 foreach (elem; T.init)
7967 return elem;
7969 assert(0);
7970 }());
7974 @safe unittest
7976 static assert(is(ForeachType!(uint[]) == uint));
7977 static assert(is(ForeachType!string == immutable(char)));
7978 static assert(is(ForeachType!(string[string]) == string));
7979 static assert(is(ForeachType!(inout(int)[]) == inout(int)));
7984 * Strips off all `enum`s from type `T`.
7986 template OriginalType(T)
7988 import core.internal.traits : _OriginalType = OriginalType;
7989 alias OriginalType = _OriginalType!T;
7993 @safe unittest
7995 enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
7996 enum F : E { a = E.a }
7997 alias G = const(F);
7998 static assert(is(OriginalType!E == real));
7999 static assert(is(OriginalType!F == real));
8000 static assert(is(OriginalType!G == const real));
8004 * Get the Key type of an Associative Array.
8006 alias KeyType(V : V[K], K) = K;
8009 @safe unittest
8011 alias Hash = int[string];
8012 static assert(is(KeyType!Hash == string));
8013 static assert(is(ValueType!Hash == int));
8014 KeyType!Hash str = "a"; // str is declared as string
8015 ValueType!Hash num = 1; // num is declared as int
8019 * Get the Value type of an Associative Array.
8021 alias ValueType(V : V[K], K) = V;
8024 @safe unittest
8026 alias Hash = int[string];
8027 static assert(is(KeyType!Hash == string));
8028 static assert(is(ValueType!Hash == int));
8029 KeyType!Hash str = "a"; // str is declared as string
8030 ValueType!Hash num = 1; // num is declared as int
8034 Params:
8035 T = A built in integral or vector type.
8037 Returns:
8038 The corresponding unsigned numeric type for `T` with the
8039 same type qualifiers.
8041 If `T` is not a integral or vector, a compile-time error is given.
8043 template Unsigned(T)
8045 template Impl(T)
8047 static if (is(T : __vector(V[N]), V, size_t N))
8048 alias Impl = __vector(Impl!V[N]);
8049 else static if (isUnsigned!T)
8050 alias Impl = T;
8051 else static if (isSigned!T && !isFloatingPoint!T)
8053 static if (is(T == byte )) alias Impl = ubyte;
8054 static if (is(T == short)) alias Impl = ushort;
8055 static if (is(T == int )) alias Impl = uint;
8056 static if (is(T == long )) alias Impl = ulong;
8057 static if (is(ucent) && is(T == cent )) alias Impl = ucent;
8059 else
8060 static assert(false, "Type " ~ T.stringof ~
8061 " does not have an Unsigned counterpart");
8064 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8068 @safe unittest
8070 static assert(is(Unsigned!(int) == uint));
8071 static assert(is(Unsigned!(long) == ulong));
8072 static assert(is(Unsigned!(const short) == const ushort));
8073 static assert(is(Unsigned!(immutable byte) == immutable ubyte));
8074 static assert(is(Unsigned!(inout int) == inout uint));
8078 /// Unsigned types are forwarded
8079 @safe unittest
8081 static assert(is(Unsigned!(uint) == uint));
8082 static assert(is(Unsigned!(const uint) == const uint));
8084 static assert(is(Unsigned!(ubyte) == ubyte));
8085 static assert(is(Unsigned!(immutable uint) == immutable uint));
8088 @safe unittest
8090 alias U1 = Unsigned!int;
8091 alias U2 = Unsigned!(const(int));
8092 alias U3 = Unsigned!(immutable(int));
8093 static assert(is(U1 == uint));
8094 static assert(is(U2 == const(uint)));
8095 static assert(is(U3 == immutable(uint)));
8096 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8098 alias UV1 = Unsigned!(__vector(int[4]));
8099 alias UV2 = Unsigned!(const(__vector(int[4])));
8100 static assert(is(UV1 == __vector(uint[4])));
8101 static assert(is(UV2 == const(__vector(uint[4]))));
8103 //struct S {}
8104 //alias U2 = Unsigned!S;
8105 //alias U3 = Unsigned!double;
8106 static if (is(ucent))
8108 alias U4 = Unsigned!cent;
8109 alias U5 = Unsigned!(const(cent));
8110 alias U6 = Unsigned!(immutable(cent));
8111 static assert(is(U4 == ucent));
8112 static assert(is(U5 == const(ucent)));
8113 static assert(is(U6 == immutable(ucent)));
8118 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
8119 than one type is of the same size, the leftmost argument of these in will be
8120 returned.
8122 template Largest(T...)
8123 if (T.length >= 1)
8125 alias Largest = T[0];
8126 static foreach (U; T[1 .. $])
8127 Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8131 @safe unittest
8133 static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8134 static assert(is(Largest!(ulong, double) == ulong));
8135 static assert(is(Largest!(double, ulong) == double));
8136 static assert(is(Largest!(uint, byte, double, short) == double));
8137 static if (is(ucent))
8138 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8142 Returns the corresponding signed type for T. T must be a numeric integral type,
8143 otherwise a compile-time error occurs.
8145 template Signed(T)
8147 template Impl(T)
8149 static if (is(T : __vector(V[N]), V, size_t N))
8150 alias Impl = __vector(Impl!V[N]);
8151 else static if (isSigned!T)
8152 alias Impl = T;
8153 else static if (isUnsigned!T)
8155 static if (is(T == ubyte )) alias Impl = byte;
8156 static if (is(T == ushort)) alias Impl = short;
8157 static if (is(T == uint )) alias Impl = int;
8158 static if (is(T == ulong )) alias Impl = long;
8159 static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8161 else
8162 static assert(false, "Type " ~ T.stringof ~
8163 " does not have an Signed counterpart");
8166 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8170 @safe unittest
8172 alias S1 = Signed!uint;
8173 static assert(is(S1 == int));
8174 alias S2 = Signed!(const(uint));
8175 static assert(is(S2 == const(int)));
8176 alias S3 = Signed!(immutable(uint));
8177 static assert(is(S3 == immutable(int)));
8178 static if (is(ucent))
8180 alias S4 = Signed!ucent;
8181 static assert(is(S4 == cent));
8185 @safe unittest
8187 static assert(is(Signed!float == float));
8188 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8190 alias SV1 = Signed!(__vector(uint[4]));
8191 alias SV2 = Signed!(const(__vector(uint[4])));
8192 static assert(is(SV1 == __vector(int[4])));
8193 static assert(is(SV2 == const(__vector(int[4]))));
8199 Returns the most negative value of the numeric type T.
8201 template mostNegative(T)
8202 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8204 static if (is(typeof(T.min_normal)))
8205 enum mostNegative = -T.max;
8206 else static if (T.min == 0)
8207 enum byte mostNegative = 0;
8208 else
8209 enum mostNegative = T.min;
8213 @safe unittest
8215 static assert(mostNegative!float == -float.max);
8216 static assert(mostNegative!double == -double.max);
8217 static assert(mostNegative!real == -real.max);
8218 static assert(mostNegative!bool == false);
8222 @safe unittest
8224 import std.meta : AliasSeq;
8226 static foreach (T; AliasSeq!(bool, byte, short, int, long))
8227 static assert(mostNegative!T == T.min);
8229 static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8230 static assert(mostNegative!T == 0);
8234 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8235 to in multi-term arithmetic expressions.
8237 template Promoted(T)
8238 if (isScalarType!T)
8240 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8244 @safe unittest
8246 ubyte a = 3, b = 5;
8247 static assert(is(typeof(a * b) == Promoted!ubyte));
8248 static assert(is(Promoted!ubyte == int));
8250 static assert(is(Promoted!(shared(bool)) == shared(int)));
8251 static assert(is(Promoted!(const(int)) == const(int)));
8252 static assert(is(Promoted!double == double));
8255 @safe unittest
8257 // promote to int:
8258 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8260 static assert(is(Promoted!T == int));
8261 static assert(is(Promoted!(shared(const T)) == shared(const int)));
8264 // already promoted:
8265 static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8267 static assert(is(Promoted!T == T));
8268 static assert(is(Promoted!(immutable(T)) == immutable(T)));
8272 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8273 // Misc.
8274 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8277 Returns the mangled name of symbol or type `sth`.
8279 `mangledName` is the same as builtin `.mangleof` property, but
8280 might be more convenient in generic code, e.g. as a template argument
8281 when invoking staticMap.
8283 enum mangledName(alias sth) = sth.mangleof;
8286 @safe unittest
8288 import std.meta : AliasSeq;
8289 alias TL = staticMap!(mangledName, int, const int, immutable int);
8290 static assert(TL == AliasSeq!("i", "xi", "yi"));
8293 version (StdUnittest) private void freeFunc(string);
8295 @safe unittest
8297 class C { int value() @property { return 0; } }
8298 static assert(mangledName!int == int.mangleof);
8299 static assert(mangledName!C == C.mangleof);
8300 static assert(mangledName!(C.value) == C.value.mangleof);
8301 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8302 static assert(mangledName!mangledName == "3std6traits11mangledName");
8303 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8304 int x;
8305 // https://issues.dlang.org/show_bug.cgi?id=9148
8306 static if (is(typeof({ return x; }) : int delegate() pure))
8307 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
8308 else
8309 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
8312 @system unittest
8314 // @system due to demangle
8315 // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8316 import std.demangle : demangle;
8317 int foo;
8318 auto foo_demangled = demangle(mangledName!foo);
8319 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8320 foo_demangled);
8322 void bar();
8323 auto bar_demangled = demangle(mangledName!bar);
8324 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8329 // XXX Select & select should go to another module. (functional or algorithm?)
8332 Aliases itself to `T[0]` if the boolean `condition` is `true`
8333 and to `T[1]` otherwise.
8335 template Select(bool condition, T...)
8336 if (T.length == 2)
8338 import std.meta : Alias;
8339 alias Select = Alias!(T[!condition]);
8343 @safe unittest
8345 // can select types
8346 static assert(is(Select!(true, int, long) == int));
8347 static assert(is(Select!(false, int, long) == long));
8348 static struct Foo {}
8349 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8351 // can select symbols
8352 int a = 1;
8353 int b = 2;
8354 alias selA = Select!(true, a, b);
8355 alias selB = Select!(false, a, b);
8356 assert(selA == 1);
8357 assert(selB == 2);
8359 // can select (compile-time) expressions
8360 enum val = Select!(false, -4, 9 - 6);
8361 static assert(val == 3);
8365 Select one of two functions to run via template parameter.
8367 Params:
8368 cond = A `bool` which determines which function is run
8369 a = The first function
8370 b = The second function
8372 Returns:
8373 `a` without evaluating `b` if `cond` is `true`.
8374 Otherwise, returns `b` without evaluating `a`.
8376 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8377 /// Ditto
8378 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8381 @safe unittest
8383 real run() { return 0; }
8384 int fail() { assert(0); }
8385 auto a = select!true(run(), fail());
8386 auto b = select!false(fail(), run());
8387 static assert(is(typeof(a) == real));
8388 static assert(is(typeof(b) == real));
8392 Determine if a symbol has a given
8393 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8395 See_Also:
8396 $(LREF getUDAs)
8398 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8401 @safe unittest
8403 enum E;
8404 struct S {}
8406 @("alpha") int a;
8407 static assert(hasUDA!(a, "alpha"));
8408 static assert(!hasUDA!(a, S));
8409 static assert(!hasUDA!(a, E));
8411 @(E) int b;
8412 static assert(!hasUDA!(b, "alpha"));
8413 static assert(!hasUDA!(b, S));
8414 static assert(hasUDA!(b, E));
8416 @E int c;
8417 static assert(!hasUDA!(c, "alpha"));
8418 static assert(!hasUDA!(c, S));
8419 static assert(hasUDA!(c, E));
8421 @(S, E) int d;
8422 static assert(!hasUDA!(d, "alpha"));
8423 static assert(hasUDA!(d, S));
8424 static assert(hasUDA!(d, E));
8426 @S int e;
8427 static assert(!hasUDA!(e, "alpha"));
8428 static assert(hasUDA!(e, S));
8429 static assert(!hasUDA!(e, S()));
8430 static assert(!hasUDA!(e, E));
8432 @S() int f;
8433 static assert(!hasUDA!(f, "alpha"));
8434 static assert(hasUDA!(f, S));
8435 static assert(hasUDA!(f, S()));
8436 static assert(!hasUDA!(f, E));
8438 @(S, E, "alpha") int g;
8439 static assert(hasUDA!(g, "alpha"));
8440 static assert(hasUDA!(g, S));
8441 static assert(hasUDA!(g, E));
8443 @(100) int h;
8444 static assert(hasUDA!(h, 100));
8446 struct Named { string name; }
8448 @Named("abc") int i;
8449 static assert(hasUDA!(i, Named));
8450 static assert(hasUDA!(i, Named("abc")));
8451 static assert(!hasUDA!(i, Named("def")));
8453 struct AttrT(T)
8455 string name;
8456 T value;
8459 @AttrT!int("answer", 42) int j;
8460 static assert(hasUDA!(j, AttrT));
8461 static assert(hasUDA!(j, AttrT!int));
8462 static assert(!hasUDA!(j, AttrT!string));
8464 @AttrT!string("hello", "world") int k;
8465 static assert(hasUDA!(k, AttrT));
8466 static assert(!hasUDA!(k, AttrT!int));
8467 static assert(hasUDA!(k, AttrT!string));
8469 struct FuncAttr(alias f) { alias func = f; }
8470 static int fourtyTwo() { return 42; }
8471 static size_t getLen(string s) { return s.length; }
8473 @FuncAttr!getLen int l;
8474 static assert(hasUDA!(l, FuncAttr));
8475 static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8476 static assert(hasUDA!(l, FuncAttr!getLen));
8477 static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8478 static assert(!hasUDA!(l, FuncAttr!getLen()));
8480 @FuncAttr!getLen() int m;
8481 static assert(hasUDA!(m, FuncAttr));
8482 static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8483 static assert(hasUDA!(m, FuncAttr!getLen));
8484 static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8485 static assert(hasUDA!(m, FuncAttr!getLen()));
8489 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8490 from the given symbol.
8492 If the UDA is a type, then any UDAs of the same type on the symbol will
8493 match. If the UDA is a template for a type, then any UDA which is an
8494 instantiation of that template will match. And if the UDA is a value,
8495 then any UDAs on the symbol which are equal to that value will match.
8497 See_Also:
8498 $(LREF hasUDA)
8500 template getUDAs(alias symbol, alias attribute)
8502 import std.meta : Filter;
8504 alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8508 @safe unittest
8510 struct Attr
8512 string name;
8513 int value;
8516 @Attr("Answer", 42) int a;
8517 static assert(getUDAs!(a, Attr).length == 1);
8518 static assert(getUDAs!(a, Attr)[0].name == "Answer");
8519 static assert(getUDAs!(a, Attr)[0].value == 42);
8521 @(Attr("Answer", 42), "string", 9999) int b;
8522 static assert(getUDAs!(b, Attr).length == 1);
8523 static assert(getUDAs!(b, Attr)[0].name == "Answer");
8524 static assert(getUDAs!(b, Attr)[0].value == 42);
8526 @Attr("Answer", 42) @Attr("Pi", 3) int c;
8527 static assert(getUDAs!(c, Attr).length == 2);
8528 static assert(getUDAs!(c, Attr)[0].name == "Answer");
8529 static assert(getUDAs!(c, Attr)[0].value == 42);
8530 static assert(getUDAs!(c, Attr)[1].name == "Pi");
8531 static assert(getUDAs!(c, Attr)[1].value == 3);
8533 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8534 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8535 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8537 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8539 struct AttrT(T)
8541 string name;
8542 T value;
8545 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8546 static assert(getUDAs!(d, AttrT).length == 2);
8547 static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8548 static assert(getUDAs!(d, AttrT)[0].value == 42);
8549 static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8550 static assert(getUDAs!(d, AttrT)[1].value == 3);
8552 static assert(getUDAs!(d, AttrT!uint).length == 1);
8553 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8554 static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8556 static assert(getUDAs!(d, AttrT!int).length == 1);
8557 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8558 static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8560 struct SimpleAttr {}
8562 @SimpleAttr int e;
8563 static assert(getUDAs!(e, SimpleAttr).length == 1);
8564 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8566 @SimpleAttr() int f;
8567 static assert(getUDAs!(f, SimpleAttr).length == 1);
8568 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8570 struct FuncAttr(alias f) { alias func = f; }
8571 static int add42(int v) { return v + 42; }
8572 static string concat(string l, string r) { return l ~ r; }
8574 @FuncAttr!add42 int g;
8575 static assert(getUDAs!(g, FuncAttr).length == 1);
8576 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8578 static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8579 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8581 static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8583 static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8584 static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8586 @FuncAttr!add42() int h;
8587 static assert(getUDAs!(h, FuncAttr).length == 1);
8588 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8590 static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8591 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8593 static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8594 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8596 static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8597 static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8599 @("alpha") @(42) int i;
8600 static assert(getUDAs!(i, "alpha").length == 1);
8601 static assert(getUDAs!(i, "alpha")[0] == "alpha");
8603 static assert(getUDAs!(i, 42).length == 1);
8604 static assert(getUDAs!(i, 42)[0] == 42);
8606 static assert(getUDAs!(i, 'c').length == 0);
8609 private template isDesiredUDA(alias attribute)
8611 template isDesiredUDA(alias toCheck)
8613 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8615 static if (__traits(compiles, toCheck == attribute))
8616 enum isDesiredUDA = toCheck == attribute;
8617 else
8618 enum isDesiredUDA = false;
8620 else static if (is(typeof(toCheck)))
8622 static if (__traits(isTemplate, attribute))
8623 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck));
8624 else
8625 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8627 else static if (__traits(isTemplate, attribute))
8628 enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8629 else
8630 enum isDesiredUDA = is(toCheck == attribute);
8635 Params:
8636 symbol = The aggregate type or module to search
8637 attribute = The user-defined attribute to search for
8639 Returns:
8640 All symbols within `symbol` that have the given UDA `attribute`.
8642 Note:
8643 This is not recursive; it will not search for symbols within symbols such as
8644 nested structs or unions.
8646 template getSymbolsByUDA(alias symbol, alias attribute)
8648 alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8650 // if the symbol itself has the UDA, tack it on to the front of the list
8651 static if (hasUDA!(symbol, attribute))
8652 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8653 else
8654 alias getSymbolsByUDA = membersWithUDA;
8658 @safe unittest
8660 enum Attr;
8661 struct A
8663 @Attr int a;
8664 int b;
8667 static assert(getSymbolsByUDA!(A, Attr).length == 1);
8668 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8672 @safe unittest
8674 enum Attr;
8676 static struct A
8678 @Attr int a;
8679 int b;
8680 @Attr void doStuff() {}
8681 void doOtherStuff() {}
8682 static struct Inner
8684 // Not found by getSymbolsByUDA
8685 @Attr int c;
8689 // Finds both variables and functions with the attribute, but
8690 // doesn't include the variables and functions without it.
8691 static assert(getSymbolsByUDA!(A, Attr).length == 2);
8692 // Can access attributes on the symbols returned by getSymbolsByUDA.
8693 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8694 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8697 /// Finds multiple attributes
8698 @safe unittest
8700 static struct UDA { string name; }
8702 static struct B
8704 @UDA("X")
8705 int x;
8706 @UDA("Y")
8707 int y;
8708 @(100)
8709 int z;
8712 // Finds both UDA attributes.
8713 static assert(getSymbolsByUDA!(B, UDA).length == 2);
8714 // Finds one `100` attribute.
8715 static assert(getSymbolsByUDA!(B, 100).length == 1);
8716 // Can get the value of the UDA from the return value
8717 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8720 /// Checks for UDAs on the aggregate symbol itself
8721 @safe unittest
8723 static struct UDA { string name; }
8725 @UDA("A")
8726 static struct C
8728 @UDA("B")
8729 int d;
8732 static assert(getSymbolsByUDA!(C, UDA).length == 2);
8733 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8734 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8737 /// Finds nothing if there is no member with specific UDA
8738 @safe unittest
8740 static struct UDA { string name; }
8742 static struct D
8744 int x;
8747 static assert(getSymbolsByUDA!(D, UDA).length == 0);
8750 // https://issues.dlang.org/show_bug.cgi?id=18314
8751 @safe unittest
8753 enum attr1;
8754 enum attr2;
8756 struct A
8758 @attr1
8759 int n;
8760 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8761 //@attr1
8762 //void foo()(string){}
8763 @attr1
8764 void foo();
8765 @attr2
8766 void foo(int a);
8769 static assert(getSymbolsByUDA!(A, attr1).length == 2);
8770 static assert(getSymbolsByUDA!(A, attr2).length == 1);
8773 // getSymbolsByUDA fails if type has private members
8774 // https://issues.dlang.org/show_bug.cgi?id=15335
8775 @safe unittest
8777 // HasPrivateMembers has, well, private members, one of which has a UDA.
8778 import std.internal.test.uda : Attr, HasPrivateMembers;
8779 // Trying access to private member from another file therefore we do not have access
8780 // for this otherwise we get deprecation warning - not visible from module
8781 // This line is commented because `__traits(getMember)` should also consider
8782 // private members; this is not currently the case, but the PR that
8783 // fixes `__traits(getMember)` is blocked by this specific test.
8784 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8785 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8788 // getSymbolsByUDA works with structs but fails with classes
8789 // https://issues.dlang.org/show_bug.cgi?id=16387
8790 @safe unittest
8792 enum Attr;
8793 class A
8795 @Attr uint a;
8798 alias res = getSymbolsByUDA!(A, Attr);
8799 static assert(res.length == 1);
8800 static assert(res[0].stringof == "a");
8803 // getSymbolsByUDA fails on AliasSeq members
8804 // https://issues.dlang.org/show_bug.cgi?id=18884
8805 @safe unittest
8807 struct X
8809 alias A = AliasSeq!(ulong, uint);
8812 static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8815 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8816 // https://issues.dlang.org/show_bug.cgi?id=18624
8817 @safe unittest
8819 enum Attr;
8820 struct A
8822 @Attr void a();
8823 @Attr void a(int n);
8824 void b();
8825 @Attr void c();
8828 static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)");
8831 // getSymbolsByUDA no longer works on modules
8832 // https://issues.dlang.org/show_bug.cgi?id=20054
8833 version (StdUnittest)
8835 @("Issue20054")
8836 void issue20054() {}
8837 static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8840 private template isAliasSeq(Args...)
8842 static if (Args.length != 1)
8843 enum isAliasSeq = true;
8844 else
8845 enum isAliasSeq = false;
8848 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8850 import std.meta : Alias, AliasSeq, Filter;
8851 static if (names.length == 0)
8853 alias getSymbolsByUDAImpl = AliasSeq!();
8855 else
8857 alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
8859 // Filtering inaccessible members.
8860 static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
8862 alias getSymbolsByUDAImpl = tail;
8864 else
8866 alias member = __traits(getMember, symbol, names[0]);
8868 // Filtering not compiled members such as alias of basic types.
8869 static if (isAliasSeq!member || isType!member)
8871 alias getSymbolsByUDAImpl = tail;
8873 // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
8874 else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
8876 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
8877 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
8878 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
8880 else static if (hasUDA!(member, attribute))
8882 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
8884 else
8886 alias getSymbolsByUDAImpl = tail;
8893 Returns: `true` iff all types `Ts` are the same.
8895 enum bool allSameType(Ts...) =
8897 static foreach (T; Ts[Ts.length > 1 .. $])
8898 static if (!is(Ts[0] == T))
8899 if (__ctfe) // Dodge the "statement is unreachable" warning
8900 return false;
8901 return true;
8902 }();
8905 @safe unittest
8907 static assert(allSameType!());
8908 static assert(allSameType!(int));
8909 static assert(allSameType!(int, int));
8910 static assert(allSameType!(int, int, int));
8911 static assert(allSameType!(float, float, float));
8912 static assert(!allSameType!(int, double));
8913 static assert(!allSameType!(int, float, double));
8914 static assert(!allSameType!(int, float, double, real));
8915 static assert(!allSameType!(short, int, float, double, real));
8919 Returns: `true` iff the type `T` can be tested in an $(D
8920 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
8922 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
8925 @safe unittest
8927 class C;
8928 struct S1;
8929 struct S2
8931 T opCast(T)() const;
8934 static assert( ifTestable!bool);
8935 static assert( ifTestable!int);
8936 static assert( ifTestable!(S1*));
8937 static assert( ifTestable!(typeof(null)));
8938 static assert( ifTestable!(int[]));
8939 static assert( ifTestable!(int[string]));
8940 static assert( ifTestable!S2);
8941 static assert( ifTestable!C);
8942 static assert(!ifTestable!S1);
8945 @safe unittest
8947 import std.meta : AliasSeq, allSatisfy;
8948 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
8949 struct BoolWrapper { bool value; }
8950 static assert(!ifTestable!(bool, a => BoolWrapper(a)));
8954 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
8955 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
8957 * Returns:
8958 * `true` if `X` is a type, `false` otherwise
8960 enum isType(alias X) = is(X);
8963 @safe unittest
8965 struct S {
8966 template Test() {}
8968 class C {}
8969 interface I {}
8970 union U {}
8971 static assert(isType!int);
8972 static assert(isType!string);
8973 static assert(isType!(int[int]));
8974 static assert(isType!S);
8975 static assert(isType!C);
8976 static assert(isType!I);
8977 static assert(isType!U);
8979 int n;
8980 void func(){}
8981 static assert(!isType!n);
8982 static assert(!isType!func);
8983 static assert(!isType!(S.Test));
8984 static assert(!isType!(S.Test!()));
8988 * Detect whether symbol or type `X` is a function. This is different that finding
8989 * if a symbol is callable or satisfying `is(X == function)`, it finds
8990 * specifically if the symbol represents a normal function declaration, i.e.
8991 * not a delegate or a function pointer.
8993 * Returns:
8994 * `true` if `X` is a function, `false` otherwise
8996 * See_Also:
8997 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
8998 * respectively.
9000 template isFunction(alias X)
9002 static if (is(typeof(&X) U : U*) && is(U == function) ||
9003 is(typeof(&X) U == delegate))
9005 // x is a (nested) function symbol.
9006 enum isFunction = true;
9008 else static if (is(X T))
9010 // x is a type. Take the type of it and examine.
9011 enum isFunction = is(T == function);
9013 else
9014 enum isFunction = false;
9018 @safe unittest
9020 static void func(){}
9021 static assert(isFunction!func);
9023 struct S
9025 void func(){}
9027 static assert(isFunction!(S.func));
9031 * Detect whether `X` is a final method or class.
9033 * Returns:
9034 * `true` if `X` is final, `false` otherwise
9036 template isFinal(alias X)
9038 static if (is(X == class))
9039 enum isFinal = __traits(isFinalClass, X);
9040 else static if (isFunction!X)
9041 enum isFinal = __traits(isFinalFunction, X);
9042 else
9043 enum isFinal = false;
9047 @safe unittest
9049 class C
9051 void nf() {}
9052 static void sf() {}
9053 final void ff() {}
9055 final class FC { }
9057 static assert(!isFinal!(C));
9058 static assert( isFinal!(FC));
9060 static assert(!isFinal!(C.nf));
9061 static assert(!isFinal!(C.sf));
9062 static assert( isFinal!(C.ff));
9066 + Determines whether the type `S` can be copied.
9067 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9068 + Copying for structs can be disabled by using `@disable this(this)`.
9070 + Params:
9071 + S = The type to check.
9073 + Returns:
9074 + `true` if `S` can be copied. `false` otherwise.
9075 + ++/
9076 enum isCopyable(S) = __traits(isCopyable, S);
9079 @safe unittest
9081 struct S1 {} // Fine. Can be copied
9082 struct S2 { this(this) {}} // Fine. Can be copied
9083 struct S3 {@disable this(this); } // Not fine. Copying is disabled.
9084 struct S4 {S3 s;} // Not fine. A field has copying disabled.
9086 class C1 {}
9088 static assert( isCopyable!S1);
9089 static assert( isCopyable!S2);
9090 static assert(!isCopyable!S3);
9091 static assert(!isCopyable!S4);
9093 static assert(isCopyable!C1);
9094 static assert(isCopyable!int);
9095 static assert(isCopyable!(int[]));
9099 * The parameter type deduced by IFTI when an expression of type T is passed as
9100 * an argument to a template function.
9102 * For all types other than pointer and slice types, `DeducedParameterType!T`
9103 * is the same as `T`. For pointer and slice types, it is `T` with the
9104 * outer-most layer of qualifiers dropped.
9106 package(std) template DeducedParameterType(T)
9108 static if (is(T == U*, U) || is(T == U[], U))
9109 alias DeducedParameterType = Unqual!T;
9110 else
9111 alias DeducedParameterType = T;
9114 @safe unittest
9116 static assert(is(DeducedParameterType!(const(int)) == const(int)));
9117 static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
9119 static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
9120 static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
9123 @safe unittest
9125 static struct NoCopy
9127 @disable this(this);
9130 static assert(is(DeducedParameterType!NoCopy == NoCopy));
9133 @safe unittest
9135 static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
9138 private auto dip1000Test(int x) {return *&x;}
9139 // We don't use isSafe, because betterC client code needs to instantiate
9140 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9141 // __cmp of two strings, so using it would instantate that here instead. That
9142 // won't do because betterC compilations do not link the Phobos binary in.
9143 package(std) enum dip1000Enabled
9144 = is(typeof(&dip1000Test) : int function(int) @safe);