d: Merge upstream dmd 568496d5b, druntime 178c44ff, phobos 574bf883b.
[official-gcc.git] / libphobos / src / std / traits.d
blob154141588baa691efabad1ae0058b43e4f078fc2
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 moduleName)
14 * $(LREF packageName)
15 * ))
16 * $(TR $(TD Function traits) $(TD
17 * $(LREF isFunction)
18 * $(LREF arity)
19 * $(LREF functionAttributes)
20 * $(LREF hasFunctionAttributes)
21 * $(LREF functionLinkage)
22 * $(LREF FunctionTypeOf)
23 * $(LREF isSafe)
24 * $(LREF isUnsafe)
25 * $(LREF isFinal)
26 * $(LREF ParameterDefaults)
27 * $(LREF ParameterIdentifierTuple)
28 * $(LREF ParameterStorageClassTuple)
29 * $(LREF Parameters)
30 * $(LREF ReturnType)
31 * $(LREF SetFunctionAttributes)
32 * $(LREF variadicFunctionStyle)
33 * ))
34 * $(TR $(TD Aggregate Type traits) $(TD
35 * $(LREF BaseClassesTuple)
36 * $(LREF BaseTypeTuple)
37 * $(LREF classInstanceAlignment)
38 * $(LREF EnumMembers)
39 * $(LREF FieldNameTuple)
40 * $(LREF Fields)
41 * $(LREF hasAliasing)
42 * $(LREF hasElaborateAssign)
43 * $(LREF hasElaborateCopyConstructor)
44 * $(LREF hasElaborateDestructor)
45 * $(LREF hasElaborateMove)
46 * $(LREF hasIndirections)
47 * $(LREF hasMember)
48 * $(LREF hasStaticMember)
49 * $(LREF hasNested)
50 * $(LREF hasUnsharedAliasing)
51 * $(LREF InterfacesTuple)
52 * $(LREF isInnerClass)
53 * $(LREF isNested)
54 * $(LREF MemberFunctionsTuple)
55 * $(LREF RepresentationTypeTuple)
56 * $(LREF TemplateArgsOf)
57 * $(LREF TemplateOf)
58 * $(LREF TransitiveBaseTypeTuple)
59 * ))
60 * $(TR $(TD Type Conversion) $(TD
61 * $(LREF CommonType)
62 * $(LREF AllImplicitConversionTargets)
63 * $(LREF ImplicitConversionTargets)
64 * $(LREF CopyTypeQualifiers)
65 * $(LREF CopyConstness)
66 * $(LREF isAssignable)
67 * $(LREF isCovariantWith)
68 * $(LREF isImplicitlyConvertible)
69 * ))
70 * $(TR $(TD SomethingTypeOf) $(TD
71 * $(LREF rvalueOf)
72 * $(LREF lvalueOf)
73 * $(LREF InoutOf)
74 * $(LREF ConstOf)
75 * $(LREF SharedOf)
76 * $(LREF SharedInoutOf)
77 * $(LREF SharedConstOf)
78 * $(LREF SharedConstInoutOf)
79 * $(LREF ImmutableOf)
80 * $(LREF QualifierOf)
81 * ))
82 * $(TR $(TD Categories of types) $(TD
83 * $(LREF allSameType)
84 * $(LREF ifTestable)
85 * $(LREF isType)
86 * $(LREF isAggregateType)
87 * $(LREF isArray)
88 * $(LREF isAssociativeArray)
89 * $(LREF isAutodecodableString)
90 * $(LREF isBasicType)
91 * $(LREF isBoolean)
92 * $(LREF isBuiltinType)
93 * $(LREF isCopyable)
94 * $(LREF isDynamicArray)
95 * $(LREF isEqualityComparable)
96 * $(LREF isFloatingPoint)
97 * $(LREF isIntegral)
98 * $(LREF isNarrowString)
99 * $(LREF isConvertibleToString)
100 * $(LREF isNumeric)
101 * $(LREF isOrderingComparable)
102 * $(LREF isPointer)
103 * $(LREF isScalarType)
104 * $(LREF isSigned)
105 * $(LREF isSIMDVector)
106 * $(LREF isSomeChar)
107 * $(LREF isSomeString)
108 * $(LREF isStaticArray)
109 * $(LREF isUnsigned)
110 * ))
111 * $(TR $(TD Type behaviours) $(TD
112 * $(LREF isAbstractClass)
113 * $(LREF isAbstractFunction)
114 * $(LREF isCallable)
115 * $(LREF isDelegate)
116 * $(LREF isExpressions)
117 * $(LREF isFinalClass)
118 * $(LREF isFinalFunction)
119 * $(LREF isFunctionPointer)
120 * $(LREF isInstanceOf)
121 * $(LREF isIterable)
122 * $(LREF isMutable)
123 * $(LREF isSomeFunction)
124 * $(LREF isTypeTuple)
125 * ))
126 * $(TR $(TD General Types) $(TD
127 * $(LREF ForeachType)
128 * $(LREF KeyType)
129 * $(LREF Largest)
130 * $(LREF mostNegative)
131 * $(LREF OriginalType)
132 * $(LREF PointerTarget)
133 * $(LREF Signed)
134 * $(LREF Unconst)
135 * $(LREF Unqual)
136 * $(LREF Unsigned)
137 * $(LREF ValueType)
138 * $(LREF Promoted)
139 * ))
140 * $(TR $(TD Misc) $(TD
141 * $(LREF mangledName)
142 * $(LREF Select)
143 * $(LREF select)
144 * ))
145 * $(TR $(TD User-Defined Attributes) $(TD
146 * $(LREF hasUDA)
147 * $(LREF getUDAs)
148 * $(LREF getSymbolsByUDA)
149 * ))
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" : "");
794 string addQualifiers(string typeString,
795 bool addConst, bool addImmutable, bool addShared, bool addInout)
797 auto result = typeString;
798 if (addShared)
800 result = "shared(" ~ result ~")";
802 if (addConst || addImmutable || addInout)
804 result = (addConst ? "const" : addImmutable ? "immutable" : "inout")
805 ~ "(" ~ result ~ ")";
807 return result;
810 // Convenience template to avoid copy-paste
811 template chain(string current)
813 enum chain = addQualifiers(current,
814 qualifiers[_const] && !alreadyConst,
815 qualifiers[_immutable] && !alreadyImmutable,
816 qualifiers[_shared] && !alreadyShared,
817 qualifiers[_inout] && !alreadyInout);
820 static if (is(T == string))
822 enum fqnType = "string";
824 else static if (is(T == wstring))
826 enum fqnType = "wstring";
828 else static if (is(T == dstring))
830 enum fqnType = "dstring";
832 else static if (isBasicType!T && !is(T == enum))
834 enum fqnType = chain!((Unqual!T).stringof);
836 else static if (isAggregateType!T || is(T == enum))
838 enum fqnType = chain!(fqnSym!T);
840 else static if (isStaticArray!T)
842 import std.conv : to;
843 enum fqnType = chain!(
844 fqnType!(typeof(T.init[0]), qualifiers) ~ "[" ~ to!string(T.length) ~ "]"
847 else static if (isArray!T)
849 enum fqnType = chain!(
850 fqnType!(typeof(T.init[0]), qualifiers) ~ "[]"
853 else static if (isAssociativeArray!T)
855 enum fqnType = chain!(
856 fqnType!(ValueType!T, qualifiers) ~ '[' ~ fqnType!(KeyType!T, noQualifiers) ~ ']'
859 else static if (isSomeFunction!T)
861 static if (is(T F == delegate))
863 enum qualifierString =
864 (is(F == shared) ? " shared" : "")
865 ~ (is(F == inout) ? " inout" :
866 is(F == immutable) ? " immutable" :
867 is(F == const) ? " const" : "");
868 enum fqnType = chain!(
869 linkageString!T
870 ~ fqnType!(ReturnType!T, noQualifiers)
871 ~ " delegate(" ~ parametersTypeString!(T) ~ ")"
872 ~ functionAttributeString!T
873 ~ qualifierString
876 else
878 enum fqnType = chain!(
879 linkageString!T
880 ~ fqnType!(ReturnType!T, noQualifiers)
881 ~ (isFunctionPointer!T ? " function(" : "(")
882 ~ parametersTypeString!(T) ~ ")"
883 ~ functionAttributeString!T
887 else static if (isPointer!T)
889 enum fqnType = chain!(
890 fqnType!(PointerTarget!T, qualifiers) ~ "*"
893 else static if (is(T : __vector(V[N]), V, size_t N))
895 import std.conv : to;
896 enum fqnType = chain!(
897 "__vector(" ~ fqnType!(V, qualifiers) ~ "[" ~ N.to!string ~ "])"
900 else
901 // In case something is forgotten
902 static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string");
905 @safe unittest
907 import std.format : format;
908 alias fqn = fullyQualifiedName;
910 // Verify those 2 are the same for simple case
911 alias Ambiguous = const(QualifiedNameTests.Inner);
912 static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false));
914 // Main tests
915 enum inner_name = "std.traits.QualifiedNameTests.Inner";
916 with (QualifiedNameTests)
918 // Special cases
919 static assert(fqn!(string) == "string");
920 static assert(fqn!(wstring) == "wstring");
921 static assert(fqn!(dstring) == "dstring");
922 static assert(fqn!(void) == "void");
923 static assert(fqn!(const(void)) == "const(void)");
924 static assert(fqn!(shared(void)) == "shared(void)");
925 static assert(fqn!(shared const(void)) == "const(shared(void))");
926 static assert(fqn!(shared inout(void)) == "inout(shared(void))");
927 static assert(fqn!(shared inout const(void)) == "const(shared(void))");
928 static assert(fqn!(inout(void)) == "inout(void)");
929 static assert(fqn!(inout const(void)) == "const(void)");
930 static assert(fqn!(immutable(void)) == "immutable(void)");
932 // Basic qualified name
933 static assert(fqn!(Inner) == inner_name);
934 static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type
935 static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol
937 // Array types
938 static assert(fqn!(typeof(array)) == format("%s[]", inner_name));
939 static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name));
940 static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name));
942 // qualified key for AA
943 static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name));
945 // Qualified composed data types
946 static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name));
948 // Function types + function attributes
949 static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref",
950 inner_name, inner_name));
951 static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name));
952 static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name));
953 static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name));
954 static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout");
955 static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name));
956 static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name));
958 // Delegate type with qualified function type
959 static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~
960 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name));
962 // Variable argument function types
963 static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)");
964 static assert(fqn!(typeof(dVarArg)) == "void(...)");
965 static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)");
966 static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)");
968 // SIMD vector
969 static if (is(__vector(float[4])))
971 static assert(fqn!(__vector(float[4])) == "__vector(float[4])");
976 /***
977 * Get the type of the return value from a function,
978 * a pointer to function, a delegate, a struct
979 * with an opCall, a pointer to a struct with an opCall,
980 * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
981 * is not part of a type, but the attribute of the function
982 * (see template $(LREF functionAttributes)).
984 template ReturnType(alias func)
985 if (isCallable!func)
987 static if (is(FunctionTypeOf!func R == return))
988 alias ReturnType = R;
989 else
990 static assert(0, "argument has no return type");
994 @safe unittest
996 int foo();
997 ReturnType!foo x; // x is declared as int
1000 @safe unittest
1002 struct G
1004 int opCall (int i) { return 1;}
1007 alias ShouldBeInt = ReturnType!G;
1008 static assert(is(ShouldBeInt == int));
1010 G g;
1011 static assert(is(ReturnType!g == int));
1013 G* p;
1014 alias pg = ReturnType!p;
1015 static assert(is(pg == int));
1017 class C
1019 int opCall (int i) { return 1;}
1022 static assert(is(ReturnType!C == int));
1024 C c;
1025 static assert(is(ReturnType!c == int));
1027 class Test
1029 int prop() @property { return 0; }
1031 alias R_Test_prop = ReturnType!(Test.prop);
1032 static assert(is(R_Test_prop == int));
1034 alias R_dglit = ReturnType!((int a) { return a; });
1035 static assert(is(R_dglit == int));
1038 /***
1039 Get, as a tuple, the types of the parameters to a function, a pointer
1040 to function, a delegate, a struct with an `opCall`, a pointer to a
1041 struct with an `opCall`, or a class with an `opCall`.
1043 template Parameters(alias func)
1044 if (isCallable!func)
1046 static if (is(FunctionTypeOf!func P == function))
1047 alias Parameters = P;
1048 else
1049 static assert(0, "argument has no parameters");
1053 @safe unittest
1055 int foo(int, long);
1056 void bar(Parameters!foo); // declares void bar(int, long);
1057 void abc(Parameters!foo[1]); // declares void abc(long);
1061 * Alternate name for $(LREF Parameters), kept for legacy compatibility.
1063 alias ParameterTypeTuple = Parameters;
1065 @safe unittest
1067 int foo(int i, bool b) { return 0; }
1068 static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool)));
1069 static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool)));
1071 struct S { real opCall(real r, int i) { return 0.0; } }
1072 S s;
1073 static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int)));
1074 static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int)));
1075 static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int)));
1077 class Test
1079 int prop() @property { return 0; }
1081 alias P_Test_prop = ParameterTypeTuple!(Test.prop);
1082 static assert(P_Test_prop.length == 0);
1084 alias P_dglit = ParameterTypeTuple!((int a){});
1085 static assert(P_dglit.length == 1);
1086 static assert(is(P_dglit[0] == int));
1090 Returns the number of arguments of function `func`.
1091 arity is undefined for variadic functions.
1093 template arity(alias func)
1094 if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
1096 enum size_t arity = Parameters!func.length;
1100 @safe unittest
1102 void foo(){}
1103 static assert(arity!foo == 0);
1104 void bar(uint){}
1105 static assert(arity!bar == 1);
1106 void variadicFoo(uint...){}
1107 static assert(!__traits(compiles, arity!variadicFoo));
1110 // https://issues.dlang.org/show_bug.cgi?id=11389
1111 @safe unittest
1113 alias TheType = size_t function( string[] );
1114 static assert(arity!TheType == 1);
1118 Get tuple, one per function parameter, of the storage classes of the parameters.
1119 Params:
1120 func = function symbol or type of function, delegate, or pointer to function
1121 Returns:
1122 A tuple of ParameterStorageClass bits
1124 enum ParameterStorageClass : uint
1127 * These flags can be bitwise OR-ed together to represent complex storage
1128 * class.
1130 none = 0x00,
1131 in_ = 0x01, /// ditto
1132 ref_ = 0x02, /// ditto
1133 out_ = 0x04, /// ditto
1134 lazy_ = 0x08, /// ditto
1135 scope_ = 0x10, /// ditto
1136 return_ = 0x20, /// ditto
1139 /// ditto
1140 template ParameterStorageClassTuple(alias func)
1141 if (isCallable!func)
1143 alias Func = FunctionTypeOf!func;
1145 static if (is(Func PT == __parameters))
1147 template StorageClass(size_t i)
1149 static if (i < PT.length)
1151 alias StorageClass = AliasSeq!(
1152 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)),
1153 StorageClass!(i + 1));
1155 else
1156 alias StorageClass = AliasSeq!();
1158 alias ParameterStorageClassTuple = StorageClass!0;
1160 else
1162 static assert(0, func[0].stringof ~ " is not a function");
1163 alias ParameterStorageClassTuple = AliasSeq!();
1168 @safe unittest
1170 alias STC = ParameterStorageClass; // shorten the enum name
1172 void func(ref int ctx, out real result, in real param, void* ptr)
1175 alias pstc = ParameterStorageClassTuple!func;
1176 static assert(pstc.length == 4); // number of parameters
1177 static assert(pstc[0] == STC.ref_);
1178 static assert(pstc[1] == STC.out_);
1179 version (none)
1181 // TODO: When the DMD PR (dlang/dmd#11474) gets merged,
1182 // remove the versioning and the second test
1183 static assert(pstc[2] == STC.in_);
1184 // This is the current behavior, before `in` is fixed to not be an alias
1185 static assert(pstc[2] == STC.scope_);
1187 static assert(pstc[3] == STC.none);
1191 Convert the result of `__traits(getParameterStorageClasses)`
1192 to $(LREF ParameterStorageClass) `enum`s.
1194 Params:
1195 Attribs = The return value of `__traits(getParameterStorageClasses)`
1196 Returns:
1197 The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s.
1199 template extractParameterStorageClassFlags(Attribs...)
1201 enum ParameterStorageClass extractParameterStorageClassFlags = ()
1203 auto result = ParameterStorageClass.none;
1204 static if (Attribs.length > 0)
1206 static foreach (attrib; Attribs)
1208 final switch (attrib) with (ParameterStorageClass)
1210 case "scope": result |= scope_; break;
1211 case "in": result |= in_; break;
1212 case "out": result |= out_; break;
1213 case "ref": result |= ref_; break;
1214 case "lazy": result |= lazy_; break;
1215 case "return": result |= return_; break;
1218 /* Mimic behavor of original version of ParameterStorageClassTuple()
1219 * to avoid breaking existing code.
1221 if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
1222 result = ParameterStorageClass.return_;
1224 return result;
1225 }();
1229 @safe unittest
1231 static void func(ref int ctx, out real result);
1233 enum param1 = extractParameterStorageClassFlags!(
1234 __traits(getParameterStorageClasses, func, 0)
1236 static assert(param1 == ParameterStorageClass.ref_);
1238 enum param2 = extractParameterStorageClassFlags!(
1239 __traits(getParameterStorageClasses, func, 1)
1241 static assert(param2 == ParameterStorageClass.out_);
1243 enum param3 = extractParameterStorageClassFlags!(
1244 __traits(getParameterStorageClasses, func, 0),
1245 __traits(getParameterStorageClasses, func, 1)
1247 static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_));
1250 @safe unittest
1252 alias STC = ParameterStorageClass;
1254 void noparam() {}
1255 static assert(ParameterStorageClassTuple!noparam.length == 0);
1257 ref int test(scope int*, ref int, out int, lazy int, int, return ref int i) { return i; }
1258 alias test_pstc = ParameterStorageClassTuple!test;
1259 static assert(test_pstc.length == 6);
1260 static assert(test_pstc[0] == STC.scope_);
1261 static assert(test_pstc[1] == STC.ref_);
1262 static assert(test_pstc[2] == STC.out_);
1263 static assert(test_pstc[3] == STC.lazy_);
1264 static assert(test_pstc[4] == STC.none);
1265 static assert(test_pstc[5] == STC.return_);
1267 interface Test
1269 void test_const(int) const;
1270 void test_sharedconst(int) shared const;
1272 Test testi;
1274 alias test_const_pstc = ParameterStorageClassTuple!(Test.test_const);
1275 static assert(test_const_pstc.length == 1);
1276 static assert(test_const_pstc[0] == STC.none);
1278 alias test_sharedconst_pstc = ParameterStorageClassTuple!(testi.test_sharedconst);
1279 static assert(test_sharedconst_pstc.length == 1);
1280 static assert(test_sharedconst_pstc[0] == STC.none);
1282 alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {});
1283 static assert(dglit_pstc.length == 1);
1284 static assert(dglit_pstc[0] == STC.ref_);
1286 // https://issues.dlang.org/show_bug.cgi?id=9317
1287 static inout(int) func(inout int param) { return param; }
1288 static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none);
1291 @safe unittest
1293 // https://issues.dlang.org/show_bug.cgi?id=14253
1294 static struct Foo {
1295 ref Foo opAssign(ref Foo rhs) return { return this; }
1298 alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]);
1303 Get, as a tuple, the identifiers of the parameters to a function symbol.
1305 template ParameterIdentifierTuple(alias func)
1306 if (isCallable!func)
1308 static if (is(FunctionTypeOf!func PT == __parameters))
1310 template Get(size_t i)
1312 static if (!isFunctionPointer!func && !isDelegate!func
1313 // Unnamed parameters yield CT error.
1314 && is(typeof(__traits(identifier, PT[i .. i+1])))
1315 // Filter out unnamed args, which look like (Type) instead of (Type name).
1316 && PT[i].stringof != PT[i .. i+1].stringof[1..$-1])
1318 enum Get = __traits(identifier, PT[i .. i+1]);
1320 else
1322 enum Get = "";
1326 else
1328 static assert(0, func.stringof ~ " is not a function");
1330 // Define dummy entities to avoid pointless errors
1331 template Get(size_t i) { enum Get = ""; }
1332 alias PT = AliasSeq!();
1335 template Impl(size_t i = 0)
1337 static if (i == PT.length)
1338 alias Impl = AliasSeq!();
1339 else
1340 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1343 alias ParameterIdentifierTuple = Impl!();
1347 @safe unittest
1349 int foo(int num, string name, int);
1350 static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
1353 // https://issues.dlang.org/show_bug.cgi?id=19456
1354 @safe unittest
1356 struct SomeType {}
1357 void foo(SomeType);
1358 void bar(int);
1359 static assert([ParameterIdentifierTuple!foo] == [""]);
1360 static assert([ParameterIdentifierTuple!bar] == [""]);
1363 @safe unittest
1365 alias PIT = ParameterIdentifierTuple;
1367 void bar(int num, string name, int[] array){}
1368 static assert([PIT!bar] == ["num", "name", "array"]);
1370 // might be changed in the future?
1371 void function(int num, string name) fp;
1372 static assert([PIT!fp] == ["", ""]);
1374 // might be changed in the future?
1375 void delegate(int num, string name, int[long] aa) dg;
1376 static assert([PIT!dg] == ["", "", ""]);
1378 interface Test
1380 @property string getter();
1381 @property void setter(int a);
1382 Test method(int a, long b, string c);
1384 static assert([PIT!(Test.getter)] == []);
1385 static assert([PIT!(Test.setter)] == ["a"]);
1386 static assert([PIT!(Test.method)] == ["a", "b", "c"]);
1389 // depends on internal
1390 void baw(int, string, int[]){}
1391 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1393 // depends on internal
1394 void baz(AliasSeq!(int, string, int[]) args){}
1395 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1401 Get, as a tuple, the default value of the parameters to a function symbol.
1402 If a parameter doesn't have the default value, `void` is returned instead.
1404 template ParameterDefaults(alias func)
1405 if (isCallable!func)
1407 alias param_names = ParameterIdentifierTuple!func;
1408 static if (is(FunctionTypeOf!(func) PT == __parameters))
1410 template Get(size_t i)
1412 // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1413 // To avoid a name clash, generate local names that are distinct
1414 // from the parameter name, and mix them in.
1415 enum name = param_names[i];
1416 enum args = "args" ~ (name == "args" ? "_" : "");
1417 enum val = "val" ~ (name == "val" ? "_" : "");
1418 enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1419 mixin("
1420 // workaround scope escape check, see
1421 // https://issues.dlang.org/show_bug.cgi?id=16582
1422 // should use return scope once available
1423 enum get = (PT[i .. i+1] " ~ args ~ ") @trusted
1425 // If the parameter is lazy, we force it to be evaluated
1426 // like this.
1427 auto " ~ val ~ " = " ~ args ~ "[0];
1428 auto " ~ ptr ~ " = &" ~ val ~ ";
1429 return *" ~ ptr ~ ";
1432 static if (is(typeof(get())))
1433 enum Get = get();
1434 else
1435 alias Get = void;
1436 // If default arg doesn't exist, returns void instead.
1439 else
1441 static assert(0, func.stringof ~ " is not a function");
1443 // Define dummy entities to avoid pointless errors
1444 template Get(size_t i) { enum Get = ""; }
1445 alias PT = AliasSeq!();
1448 template Impl(size_t i = 0)
1450 static if (i == PT.length)
1451 alias Impl = AliasSeq!();
1452 else
1453 alias Impl = AliasSeq!(Get!i, Impl!(i+1));
1456 alias ParameterDefaults = Impl!();
1460 @safe unittest
1462 int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
1463 static assert(is(ParameterDefaults!foo[0] == void));
1464 static assert( ParameterDefaults!foo[1] == "hello");
1465 static assert( ParameterDefaults!foo[2] == [1,2,3]);
1466 static assert( ParameterDefaults!foo[3] == 0);
1469 // https://issues.dlang.org/show_bug.cgi?id=17192
1470 @safe unittest
1472 static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1473 int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1476 alias Voids = ParameterDefaults!func;
1477 static assert(Voids.length == 12);
1478 static foreach (V; Voids) static assert(is(V == void));
1482 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1484 alias ParameterDefaultValueTuple = ParameterDefaults;
1486 @safe unittest
1488 alias PDVT = ParameterDefaultValueTuple;
1490 void bar(int n = 1, string s = "hello"){}
1491 static assert(PDVT!bar.length == 2);
1492 static assert(PDVT!bar[0] == 1);
1493 static assert(PDVT!bar[1] == "hello");
1494 static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello"))));
1496 void baz(int x, int n = 1, string s = "hello"){}
1497 static assert(PDVT!baz.length == 3);
1498 static assert(is(PDVT!baz[0] == void));
1499 static assert( PDVT!baz[1] == 1);
1500 static assert( PDVT!baz[2] == "hello");
1501 static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello"))));
1503 // property functions return empty string
1504 // https://issues.dlang.org/show_bug.cgi?id=10800
1505 @property void foo(int x = 3) { }
1506 static assert(PDVT!foo.length == 1);
1507 static assert(PDVT!foo[0] == 3);
1508 static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3))));
1510 struct Colour
1512 ubyte a,r,g,b;
1514 static immutable Colour white = Colour(255,255,255,255);
1516 // https://issues.dlang.org/show_bug.cgi?id=8106
1517 void bug8106(Colour c = Colour.white) {}
1518 //pragma(msg, PDVT!bug8106);
1519 static assert(PDVT!bug8106[0] == Colour.white);
1520 // https://issues.dlang.org/show_bug.cgi?id=16582
1521 void bug16582(scope int* val = null) {}
1522 static assert(PDVT!bug16582[0] is null);
1527 Returns the FunctionAttribute mask for function `func`.
1529 See_Also:
1530 $(LREF hasFunctionAttributes)
1532 enum FunctionAttribute : uint
1535 * These flags can be bitwise OR-ed together to represent a complex attribute.
1537 none = 0,
1538 pure_ = 1 << 0, /// ditto
1539 nothrow_ = 1 << 1, /// ditto
1540 ref_ = 1 << 2, /// ditto
1541 property = 1 << 3, /// ditto
1542 trusted = 1 << 4, /// ditto
1543 safe = 1 << 5, /// ditto
1544 nogc = 1 << 6, /// ditto
1545 system = 1 << 7, /// ditto
1546 const_ = 1 << 8, /// ditto
1547 immutable_ = 1 << 9, /// ditto
1548 inout_ = 1 << 10, /// ditto
1549 shared_ = 1 << 11, /// ditto
1550 return_ = 1 << 12, /// ditto
1551 scope_ = 1 << 13, /// ditto
1552 live = 1 << 14, /// ditto
1555 /// ditto
1556 template functionAttributes(alias func)
1557 if (isCallable!func)
1559 // @bug: workaround for opCall
1560 alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
1561 func, Unqual!(FunctionTypeOf!func));
1563 enum FunctionAttribute functionAttributes =
1564 extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))();
1568 @safe unittest
1570 alias FA = FunctionAttribute; // shorten the enum name
1572 real func(real x) pure nothrow @safe
1574 return x;
1576 static assert(functionAttributes!func & FA.pure_);
1577 static assert(functionAttributes!func & FA.safe);
1578 static assert(!(functionAttributes!func & FA.trusted)); // not @trusted
1581 @system unittest
1583 alias FA = FunctionAttribute;
1585 struct S
1587 int noF() { return 0; }
1588 int constF() const { return 0; }
1589 int immutableF() immutable { return 0; }
1590 int inoutF() inout { return 0; }
1591 int sharedF() shared { return 0; }
1593 int x;
1594 ref int refF() return { return x; }
1595 int propertyF() @property { return 0; }
1596 int nothrowF() nothrow { return 0; }
1597 int nogcF() @nogc { return 0; }
1599 int systemF() @system { return 0; }
1600 int trustedF() @trusted { return 0; }
1601 int safeF() @safe { return 0; }
1603 int pureF() pure { return 0; }
1605 int liveF() @live { return 0; }
1608 static assert(functionAttributes!(S.noF) == FA.system);
1609 static assert(functionAttributes!(typeof(S.noF)) == FA.system);
1611 static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system));
1612 static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system));
1614 static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system));
1615 static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system));
1617 static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system));
1618 static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system));
1620 static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system));
1621 static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system));
1623 static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_));
1624 static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_));
1626 static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system));
1627 static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system));
1629 static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system));
1630 static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system));
1632 static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system));
1633 static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system));
1635 static assert(functionAttributes!(S.systemF) == FA.system);
1636 static assert(functionAttributes!(typeof(S.systemF)) == FA.system);
1638 static assert(functionAttributes!(S.trustedF) == FA.trusted);
1639 static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted);
1641 static assert(functionAttributes!(S.safeF) == FA.safe);
1642 static assert(functionAttributes!(typeof(S.safeF)) == FA.safe);
1644 static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system));
1645 static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system));
1647 static assert(functionAttributes!(S.liveF) == (FA.live | FA.system));
1648 static assert(functionAttributes!(typeof(S.liveF)) == (FA.live | FA.system));
1650 int pure_nothrow() nothrow pure;
1651 void safe_nothrow() @safe nothrow;
1652 static ref int static_ref_property() @property;
1653 ref int ref_property() @property;
1655 static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system));
1656 static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system));
1658 static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_));
1659 static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_));
1661 static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system));
1662 static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system));
1664 static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system));
1665 static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system));
1667 struct S2
1669 int pure_const() const pure { return 0; }
1670 int pure_sharedconst() const shared pure { return 0; }
1673 static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system));
1674 static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system));
1676 static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1677 static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1679 static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1680 static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1682 auto safeDel = delegate() @safe { };
1683 static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1684 static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1686 auto trustedDel = delegate() @trusted { };
1687 static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1688 static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1690 auto systemDel = delegate() @system { };
1691 static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1692 static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1695 private FunctionAttribute extractAttribFlags(Attribs...)()
1697 auto res = FunctionAttribute.none;
1699 static foreach (attrib; Attribs)
1701 switch (attrib) with (FunctionAttribute)
1703 case "pure": res |= pure_; break;
1704 case "nothrow": res |= nothrow_; break;
1705 case "ref": res |= ref_; break;
1706 case "@property": res |= property; break;
1707 case "@trusted": res |= trusted; break;
1708 case "@safe": res |= safe; break;
1709 case "@nogc": res |= nogc; break;
1710 case "@system": res |= system; break;
1711 case "const": res |= const_; break;
1712 case "immutable": res |= immutable_; break;
1713 case "inout": res |= inout_; break;
1714 case "shared": res |= shared_; break;
1715 case "return": res |= return_; break;
1716 case "scope": res |= scope_; break;
1717 case "@live": res |= live; break;
1718 default: assert(0, attrib);
1722 return res;
1726 Checks whether a function has the given attributes attached.
1728 Params:
1729 args = Function to check, followed by a
1730 variadic number of function attributes as strings
1732 Returns:
1733 `true`, if the function has the list of attributes attached and `false` otherwise.
1735 See_Also:
1736 $(LREF functionAttributes)
1738 template hasFunctionAttributes(args...)
1739 if (args.length > 0 && isCallable!(args[0])
1740 && allSatisfy!(isSomeString, typeof(args[1 .. $])))
1742 enum bool hasFunctionAttributes = {
1743 import std.algorithm.searching : canFind;
1744 import std.range : only;
1745 enum funcAttribs = only(__traits(getFunctionAttributes, args[0]));
1746 static foreach (attribute; args[1 .. $])
1748 if (!funcAttribs.canFind(attribute))
1749 return false;
1751 return true;
1752 }();
1756 @safe unittest
1758 real func(real x) pure nothrow @safe;
1759 static assert(hasFunctionAttributes!(func, "@safe", "pure"));
1760 static assert(!hasFunctionAttributes!(func, "@trusted"));
1762 // for templates attributes are automatically inferred
1763 bool myFunc(T)(T b)
1765 return !b;
1767 static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
1768 static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
1771 @system unittest
1773 struct S
1775 int noF();
1776 int constF() const;
1777 int immutableF() immutable;
1778 int inoutF() inout;
1779 int sharedF() shared;
1781 ref int refF() return;
1782 int propertyF() @property;
1783 int nothrowF() nothrow;
1784 int nogcF() @nogc;
1786 int systemF() @system;
1787 int trustedF() @trusted;
1788 int safeF() @safe;
1790 int pureF() pure;
1792 int liveF() @live;
1795 // true if no args passed
1796 static assert(hasFunctionAttributes!(S.noF));
1798 static assert(hasFunctionAttributes!(S.noF, "@system"));
1799 static assert(hasFunctionAttributes!(typeof(S.noF), "@system"));
1800 static assert(!hasFunctionAttributes!(S.noF, "@system", "pure"));
1802 static assert(hasFunctionAttributes!(S.constF, "const", "@system"));
1803 static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system"));
1804 static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc"));
1806 static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system"));
1807 static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system"));
1808 static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure"));
1810 static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system"));
1811 static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system"));
1812 static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure"));
1814 static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system"));
1815 static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system"));
1816 static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted"));
1818 static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return"));
1819 static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return"));
1820 static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure"));
1822 static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system"));
1823 static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system"));
1824 static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref"));
1826 static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system"));
1827 static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system"));
1828 static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted"));
1830 static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system"));
1831 static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system"));
1832 static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref"));
1834 static assert(hasFunctionAttributes!(S.systemF, "@system"));
1835 static assert(hasFunctionAttributes!(typeof(S.systemF), "@system"));
1836 static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref"));
1838 static assert(hasFunctionAttributes!(S.trustedF, "@trusted"));
1839 static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted"));
1840 static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe"));
1842 static assert(hasFunctionAttributes!(S.safeF, "@safe"));
1843 static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe"));
1844 static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow"));
1846 static assert(hasFunctionAttributes!(S.pureF, "pure", "@system"));
1847 static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system"));
1848 static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref"));
1850 static assert(hasFunctionAttributes!(S.liveF, "@live", "@system"));
1851 static assert(hasFunctionAttributes!(typeof(S.liveF), "@live", "@system"));
1852 static assert(!hasFunctionAttributes!(S.liveF, "@live", "@system", "ref"));
1854 int pure_nothrow() nothrow pure { return 0; }
1855 void safe_nothrow() @safe nothrow { }
1856 static ref int static_ref_property() @property { return *(new int); }
1857 ref int ref_property() @property { return *(new int); }
1859 static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe"));
1860 static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe"));
1861 static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted"));
1863 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow"));
1864 static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow"));
1865 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure"));
1866 static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted"));
1868 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe"));
1869 static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe"));
1870 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow"));
1871 static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc"));
1873 static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe"));
1874 static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe"));
1875 static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc"));
1877 struct S2
1879 int pure_const() const pure { return 0; }
1880 int pure_sharedconst() const shared pure { return 0; }
1883 static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system"));
1884 static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system"));
1885 static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref"));
1887 static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system"));
1888 static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system"));
1889 static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc"));
1891 static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe"));
1892 static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe"));
1893 static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1895 auto safeDel = delegate() @safe { };
1896 static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe"));
1897 static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe"));
1898 static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system"));
1900 auto trustedDel = delegate() @trusted { };
1901 static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted"));
1902 static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted"));
1903 static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1905 auto systemDel = delegate() @system { };
1906 static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system"));
1907 static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system"));
1908 static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property"));
1911 // call functions to make CodeCov happy
1913 assert(pure_nothrow == 0);
1914 safe_nothrow;
1915 assert(static_ref_property == 0);
1916 assert(ref_property == 0);
1917 assert(S2().pure_const == 0);
1918 assert((shared S2()).pure_sharedconst == 0);
1919 cast(void) safeDel;
1920 cast(void) trustedDel;
1921 cast(void) systemDel;
1926 `true` if `func` is `@safe` or `@trusted`.
1928 template isSafe(alias func)
1929 if (isCallable!func)
1931 enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 ||
1932 (functionAttributes!func & FunctionAttribute.trusted) != 0;
1936 @safe unittest
1938 @safe int add(int a, int b) {return a+b;}
1939 @trusted int sub(int a, int b) {return a-b;}
1940 @system int mul(int a, int b) {return a*b;}
1942 static assert( isSafe!add);
1943 static assert( isSafe!sub);
1944 static assert(!isSafe!mul);
1948 @safe unittest
1950 //Member functions
1951 interface Set
1953 int systemF() @system;
1954 int trustedF() @trusted;
1955 int safeF() @safe;
1957 static assert( isSafe!(Set.safeF));
1958 static assert( isSafe!(Set.trustedF));
1959 static assert(!isSafe!(Set.systemF));
1961 //Functions
1962 @safe static void safeFunc() {}
1963 @trusted static void trustedFunc() {}
1964 @system static void systemFunc() {}
1966 static assert( isSafe!safeFunc);
1967 static assert( isSafe!trustedFunc);
1968 static assert(!isSafe!systemFunc);
1970 //Delegates
1971 auto safeDel = delegate() @safe {};
1972 auto trustedDel = delegate() @trusted {};
1973 auto systemDel = delegate() @system {};
1975 static assert( isSafe!safeDel);
1976 static assert( isSafe!trustedDel);
1977 static assert(!isSafe!systemDel);
1979 //Lambdas
1980 static assert( isSafe!({safeDel();}));
1981 static assert( isSafe!({trustedDel();}));
1982 static assert(!isSafe!({systemDel();}));
1984 //Static opCall
1985 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
1986 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
1987 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
1989 static assert( isSafe!(SafeStatic()));
1990 static assert( isSafe!(TrustedStatic()));
1991 static assert(!isSafe!(SystemStatic()));
1993 //Non-static opCall
1994 struct Safe { @safe Safe opCall() { return Safe.init; } }
1995 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
1996 struct System { @system System opCall() { return System.init; } }
1998 static assert( isSafe!(Safe.init()));
1999 static assert( isSafe!(Trusted.init()));
2000 static assert(!isSafe!(System.init()));
2005 `true` if `func` is `@system`.
2007 template isUnsafe(alias func)
2009 enum isUnsafe = !isSafe!func;
2013 @safe unittest
2015 @safe int add(int a, int b) {return a+b;}
2016 @trusted int sub(int a, int b) {return a-b;}
2017 @system int mul(int a, int b) {return a*b;}
2019 static assert(!isUnsafe!add);
2020 static assert(!isUnsafe!sub);
2021 static assert( isUnsafe!mul);
2024 @safe unittest
2026 //Member functions
2027 interface Set
2029 int systemF() @system;
2030 int trustedF() @trusted;
2031 int safeF() @safe;
2033 static assert(!isUnsafe!(Set.safeF));
2034 static assert(!isUnsafe!(Set.trustedF));
2035 static assert( isUnsafe!(Set.systemF));
2037 //Functions
2038 @safe static void safeFunc() {}
2039 @trusted static void trustedFunc() {}
2040 @system static void systemFunc() {}
2042 static assert(!isUnsafe!safeFunc);
2043 static assert(!isUnsafe!trustedFunc);
2044 static assert( isUnsafe!systemFunc);
2046 //Delegates
2047 auto safeDel = delegate() @safe {};
2048 auto trustedDel = delegate() @trusted {};
2049 auto systemDel = delegate() @system {};
2051 static assert(!isUnsafe!safeDel);
2052 static assert(!isUnsafe!trustedDel);
2053 static assert( isUnsafe!systemDel);
2055 //Lambdas
2056 static assert(!isUnsafe!({safeDel();}));
2057 static assert(!isUnsafe!({trustedDel();}));
2058 static assert( isUnsafe!({systemDel();}));
2060 //Static opCall
2061 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
2062 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
2063 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
2065 static assert(!isUnsafe!(SafeStatic()));
2066 static assert(!isUnsafe!(TrustedStatic()));
2067 static assert( isUnsafe!(SystemStatic()));
2069 //Non-static opCall
2070 struct Safe { @safe Safe opCall() { return Safe.init; } }
2071 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
2072 struct System { @system System opCall() { return System.init; } }
2074 static assert(!isUnsafe!(Safe.init()));
2075 static assert(!isUnsafe!(Trusted.init()));
2076 static assert( isUnsafe!(System.init()));
2081 Determine the linkage attribute of the function.
2082 Params:
2083 func = the function symbol, or the type of a function, delegate, or pointer to function
2084 Returns:
2085 one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
2087 template functionLinkage(alias func)
2088 if (isCallable!func)
2090 enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
2094 @safe unittest
2096 extern(D) void Dfunc() {}
2097 extern(C) void Cfunc() {}
2098 static assert(functionLinkage!Dfunc == "D");
2099 static assert(functionLinkage!Cfunc == "C");
2101 string a = functionLinkage!Dfunc;
2102 assert(a == "D");
2104 auto fp = &Cfunc;
2105 string b = functionLinkage!fp;
2106 assert(b == "C");
2109 @safe unittest
2111 interface Test
2113 void const_func() const;
2114 void sharedconst_func() shared const;
2116 static assert(functionLinkage!(Test.const_func) == "D");
2117 static assert(functionLinkage!(Test.sharedconst_func) == "D");
2119 static assert(functionLinkage!((int a){}) == "D");
2124 Determines what kind of variadic parameters function has.
2125 Params:
2126 func = function symbol or type of function, delegate, or pointer to function
2127 Returns:
2128 enum Variadic
2130 enum Variadic
2132 /// Function is not variadic.
2134 /// Function is a _C-style variadic function, which uses
2135 /// `core.stdc.stdarg`
2137 /// Function is a _D-style variadic function, which uses
2138 /// `__argptr` and `__arguments`.
2140 /// Function is a typesafe variadic function.
2141 typesafe,
2144 /// ditto
2145 template variadicFunctionStyle(alias func)
2146 if (isCallable!func)
2148 enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
2149 enum Variadic variadicFunctionStyle =
2150 (varargs == "stdarg") ? Variadic.c :
2151 (varargs == "argptr") ? Variadic.d :
2152 (varargs == "typesafe") ? Variadic.typesafe :
2153 (varargs == "none") ? Variadic.no : Variadic.no;
2157 @safe unittest
2159 void func() {}
2160 static assert(variadicFunctionStyle!func == Variadic.no);
2162 extern(C) int printf(in char*, ...);
2163 static assert(variadicFunctionStyle!printf == Variadic.c);
2166 @safe unittest
2168 import core.vararg;
2170 extern(D) void novar() {}
2171 extern(C) void cstyle(int, ...) {}
2172 extern(D) void dstyle(...) {}
2173 extern(D) void typesafe(int[]...) {}
2175 static assert(variadicFunctionStyle!novar == Variadic.no);
2176 static assert(variadicFunctionStyle!cstyle == Variadic.c);
2177 static assert(variadicFunctionStyle!dstyle == Variadic.d);
2178 static assert(variadicFunctionStyle!typesafe == Variadic.typesafe);
2180 static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe);
2185 Get the function type from a callable object `func`.
2187 Using builtin `typeof` on a property function yields the types of the
2188 property value, not of the property function itself. Still,
2189 `FunctionTypeOf` is able to obtain function types of properties.
2191 Note:
2192 Do not confuse function types with function pointer types; function types are
2193 usually used for compile-time reflection purposes.
2195 template FunctionTypeOf(alias func)
2196 if (isCallable!func)
2198 static if ((is(typeof(& func) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func) Fsym == delegate))
2200 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
2202 else static if (is(typeof(& func.opCall) Fobj == delegate) || is(typeof(& func.opCall!()) Fobj == delegate))
2204 alias FunctionTypeOf = Fobj; // HIT: callable object
2206 else static if (
2207 (is(typeof(& func.opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
2208 (is(typeof(& func.opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
2211 alias FunctionTypeOf = Ftyp; // HIT: callable type
2213 else static if (is(func T) || is(typeof(func) T))
2215 static if (is(T == function))
2216 alias FunctionTypeOf = T; // HIT: function
2217 else static if (is(T Fptr : Fptr*) && is(Fptr == function))
2218 alias FunctionTypeOf = Fptr; // HIT: function pointer
2219 else static if (is(T Fdlg == delegate))
2220 alias FunctionTypeOf = Fdlg; // HIT: delegate
2221 else
2222 static assert(0);
2224 else
2225 static assert(0);
2229 @safe unittest
2231 class C
2233 int value() @property { return 0; }
2235 static assert(is( typeof(C.value) == int ));
2236 static assert(is( FunctionTypeOf!(C.value) == function ));
2239 @system unittest
2241 int test(int a);
2242 int propGet() @property;
2243 int propSet(int a) @property;
2244 int function(int) test_fp;
2245 int delegate(int) test_dg;
2246 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) ));
2247 static assert(is( typeof(test) == FunctionTypeOf!test ));
2248 static assert(is( typeof(test) == FunctionTypeOf!test_fp ));
2249 static assert(is( typeof(test) == FunctionTypeOf!test_dg ));
2250 alias int GetterType() @property;
2251 alias int SetterType(int) @property;
2252 static assert(is( FunctionTypeOf!propGet == GetterType ));
2253 static assert(is( FunctionTypeOf!propSet == SetterType ));
2255 interface Prop { int prop() @property; }
2256 Prop prop;
2257 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType ));
2258 static assert(is( FunctionTypeOf!(prop.prop) == GetterType ));
2260 class Callable { int opCall(int) { return 0; } }
2261 auto call = new Callable;
2262 static assert(is( FunctionTypeOf!call == typeof(test) ));
2264 struct StaticCallable { static int opCall(int) { return 0; } }
2265 StaticCallable stcall_val;
2266 StaticCallable* stcall_ptr;
2267 static assert(is( FunctionTypeOf!stcall_val == typeof(test) ));
2268 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) ));
2270 struct TemplatedOpCallF { int opCall()(int) { return 0; } }
2271 static assert(is( FunctionTypeOf!TemplatedOpCallF == typeof(TemplatedOpCallF.opCall!()) ));
2273 int foovar;
2274 struct TemplatedOpCallDg { int opCall()() { return foovar; } }
2275 static assert(is( FunctionTypeOf!TemplatedOpCallDg == typeof(TemplatedOpCallDg.opCall!()) ));
2277 interface Overloads
2279 void test(string);
2280 real test(real);
2281 int test(int);
2282 int test() @property;
2284 alias ov = __traits(getVirtualFunctions, Overloads, "test");
2285 alias F_ov0 = FunctionTypeOf!(ov[0]);
2286 alias F_ov1 = FunctionTypeOf!(ov[1]);
2287 alias F_ov2 = FunctionTypeOf!(ov[2]);
2288 alias F_ov3 = FunctionTypeOf!(ov[3]);
2289 static assert(is(F_ov0* == void function(string)));
2290 static assert(is(F_ov1* == real function(real)));
2291 static assert(is(F_ov2* == int function(int)));
2292 static assert(is(F_ov3* == int function() @property));
2294 alias F_dglit = FunctionTypeOf!((int a){ return a; });
2295 static assert(is(F_dglit* : int function(int)));
2299 * Constructs a new function or delegate type with the same basic signature
2300 * as the given one, but different attributes (including linkage).
2302 * This is especially useful for adding/removing attributes to/from types in
2303 * generic code, where the actual type name cannot be spelt out.
2305 * Params:
2306 * T = The base type.
2307 * linkage = The desired linkage of the result type.
2308 * attrs = The desired $(LREF FunctionAttribute)s of the result type.
2310 template SetFunctionAttributes(T, string linkage, uint attrs)
2311 if (isFunctionPointer!T || isDelegate!T)
2313 mixin({
2314 import std.algorithm.searching : canFind;
2316 static assert(!(attrs & FunctionAttribute.trusted) ||
2317 !(attrs & FunctionAttribute.safe),
2318 "Cannot have a function/delegate that is both trusted and safe.");
2320 static immutable linkages = ["D", "C", "Windows", "C++", "System"];
2321 static assert(canFind(linkages, linkage), "Invalid linkage '" ~
2322 linkage ~ "', must be one of " ~ linkages.stringof ~ ".");
2324 string result = "alias ";
2326 static if (linkage != "D")
2327 result ~= "extern(" ~ linkage ~ ") ";
2329 static if (attrs & FunctionAttribute.ref_)
2330 result ~= "ref ";
2332 result ~= "ReturnType!T";
2334 static if (isDelegate!T)
2335 result ~= " delegate";
2336 else
2337 result ~= " function";
2339 result ~= "(";
2341 static if (Parameters!T.length > 0)
2342 result ~= "Parameters!T";
2344 enum varStyle = variadicFunctionStyle!T;
2345 static if (varStyle == Variadic.c)
2346 result ~= ", ...";
2347 else static if (varStyle == Variadic.d)
2348 result ~= "...";
2349 else static if (varStyle == Variadic.typesafe)
2350 result ~= "...";
2352 result ~= ")";
2354 static if (attrs & FunctionAttribute.pure_)
2355 result ~= " pure";
2356 static if (attrs & FunctionAttribute.nothrow_)
2357 result ~= " nothrow";
2358 static if (attrs & FunctionAttribute.property)
2359 result ~= " @property";
2360 static if (attrs & FunctionAttribute.trusted)
2361 result ~= " @trusted";
2362 static if (attrs & FunctionAttribute.safe)
2363 result ~= " @safe";
2364 static if (attrs & FunctionAttribute.nogc)
2365 result ~= " @nogc";
2366 static if (attrs & FunctionAttribute.system)
2367 result ~= " @system";
2368 static if (attrs & FunctionAttribute.const_)
2369 result ~= " const";
2370 static if (attrs & FunctionAttribute.immutable_)
2371 result ~= " immutable";
2372 static if (attrs & FunctionAttribute.inout_)
2373 result ~= " inout";
2374 static if (attrs & FunctionAttribute.shared_)
2375 result ~= " shared";
2376 static if (attrs & FunctionAttribute.return_)
2377 result ~= " return";
2378 static if (attrs & FunctionAttribute.live)
2379 result ~= " @live";
2381 result ~= " SetFunctionAttributes;";
2382 return result;
2383 }());
2386 /// Ditto
2387 template SetFunctionAttributes(T, string linkage, uint attrs)
2388 if (is(T == function))
2390 // To avoid a lot of syntactic headaches, we just use the above version to
2391 // operate on the corresponding function pointer type and then remove the
2392 // indirection again.
2393 alias SetFunctionAttributes = FunctionTypeOf!(SetFunctionAttributes!(T*, linkage, attrs));
2397 @safe unittest
2399 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
2401 auto assumePure(T)(T t)
2402 if (isFunctionPointer!T || isDelegate!T)
2404 enum attrs = functionAttributes!T | FunctionAttribute.pure_;
2405 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
2408 int f()
2410 import core.thread : getpid;
2411 return getpid();
2414 int g() pure @trusted
2416 auto pureF = assumePure(&f);
2417 return pureF();
2419 assert(g() > 0);
2422 version (StdUnittest)
2424 private:
2425 // Some function types to test.
2426 int sc(scope int, ref int, out int, lazy int, int);
2427 extern(System) int novar();
2428 extern(C) int cstyle(int, ...);
2429 extern(D) int dstyle(...);
2430 extern(D) int typesafe(int[]...);
2432 @safe unittest
2434 import std.algorithm.iteration : reduce;
2436 alias FA = FunctionAttribute;
2437 static foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle),
2438 typeof(&dstyle), typeof(&typesafe)))
2440 static foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT))
2442 enum linkage = functionLinkage!T;
2443 enum attrs = functionAttributes!T;
2445 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T),
2446 "Identity check failed for: " ~ T.stringof);
2448 // Check that all linkage types work (D-style variadics require D linkage).
2449 static if (variadicFunctionStyle!T != Variadic.d)
2451 static foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++"))
2453 alias New = SetFunctionAttributes!(T, newLinkage, attrs);
2454 static assert(functionLinkage!New == newLinkage,
2455 "Linkage test failed for: " ~ T.stringof ~ ", " ~ newLinkage ~
2456 " (got " ~ New.stringof ~ ")");
2460 // Add @safe.
2461 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe);
2462 static assert(functionAttributes!T1 == FA.safe);
2464 // Add all known attributes, excluding conflicting ones.
2465 enum allAttrs = reduce!"a | b"([EnumMembers!FA])
2466 & ~FA.safe & ~FA.property & ~FA.const_ & ~FA.immutable_ & ~FA.inout_
2467 & ~FA.shared_ & ~FA.system & ~FA.return_ & ~FA.scope_;
2469 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs);
2470 static assert(functionAttributes!T2 == allAttrs);
2472 // Strip all attributes again.
2473 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none);
2474 static assert(is(T3 == T));
2480 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2481 // Aggregate Types
2482 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2485 Determines whether `T` is a class nested inside another class
2486 and that `T.outer` is the implicit reference to the outer class
2487 (i.e. `outer` has not been used as a field or method name)
2489 Params:
2490 T = type to test
2492 Returns:
2493 `true` if `T` is a class nested inside another, with the conditions described above;
2494 `false` otherwise
2496 template isInnerClass(T)
2497 if (is(T == class))
2499 static if (is(typeof(T.outer)))
2501 bool hasOuterMember(string[] members...)
2503 foreach (m; members)
2505 if (m == "outer")
2506 return true;
2508 return false;
2510 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) &&
2511 !hasOuterMember(__traits(allMembers, T));
2513 else
2514 enum isInnerClass = false;
2518 @safe unittest
2520 class C
2522 int outer;
2524 static assert(!isInnerClass!C);
2526 class Outer1
2528 class Inner1 { }
2529 class Inner2
2531 int outer;
2534 static assert(isInnerClass!(Outer1.Inner1));
2535 static assert(!isInnerClass!(Outer1.Inner2));
2537 static class Outer2
2539 static class Inner
2541 int outer;
2544 static assert(!isInnerClass!(Outer2.Inner));
2548 Determines whether `T` has its own context pointer.
2549 `T` must be either `class`, `struct`, or `union`.
2551 template isNested(T)
2552 if (is(T == class) || is(T == struct) || is(T == union))
2554 enum isNested = __traits(isNested, T);
2558 @safe unittest
2560 static struct S { }
2561 static assert(!isNested!S);
2563 int i;
2564 struct NestedStruct { void f() { ++i; } }
2565 static assert(isNested!NestedStruct);
2569 Determines whether `T` or any of its representation types
2570 have a context pointer.
2572 template hasNested(T)
2574 import std.meta : Filter;
2576 static if (isStaticArray!T && T.length)
2577 enum hasNested = hasNested!(typeof(T.init[0]));
2578 else static if (is(T == class) || is(T == struct) || is(T == union))
2580 // prevent infinite recursion for class with member of same type
2581 enum notSame(U) = !is(immutable T == immutable U);
2582 enum hasNested = isNested!T ||
2583 anySatisfy!(.hasNested, Filter!(notSame, Fields!T));
2585 else
2586 enum hasNested = false;
2590 @safe unittest
2592 static struct S { }
2594 int i;
2595 struct NS { void f() { ++i; } }
2597 static assert(!hasNested!(S[2]));
2598 static assert(hasNested!(NS[2]));
2601 @safe unittest
2603 static assert(!__traits(compiles, isNested!int));
2604 static assert(!hasNested!int);
2606 static struct StaticStruct { }
2607 static assert(!isNested!StaticStruct);
2608 static assert(!hasNested!StaticStruct);
2610 int i;
2611 struct NestedStruct { void f() { ++i; } }
2612 static assert( isNested!NestedStruct);
2613 static assert( hasNested!NestedStruct);
2614 static assert( isNested!(immutable NestedStruct));
2615 static assert( hasNested!(immutable NestedStruct));
2617 static assert(!__traits(compiles, isNested!(NestedStruct[1])));
2618 static assert( hasNested!(NestedStruct[1]));
2619 static assert(!hasNested!(NestedStruct[0]));
2621 struct S1 { NestedStruct nested; }
2622 static assert(!isNested!S1);
2623 static assert( hasNested!S1);
2625 static struct S2 { NestedStruct nested; }
2626 static assert(!isNested!S2);
2627 static assert( hasNested!S2);
2629 static struct S3 { NestedStruct[0] nested; }
2630 static assert(!isNested!S3);
2631 static assert(!hasNested!S3);
2633 static union U { NestedStruct nested; }
2634 static assert(!isNested!U);
2635 static assert( hasNested!U);
2637 static class StaticClass { }
2638 static assert(!isNested!StaticClass);
2639 static assert(!hasNested!StaticClass);
2641 class NestedClass { void f() { ++i; } }
2642 static assert( isNested!NestedClass);
2643 static assert( hasNested!NestedClass);
2644 static assert( isNested!(immutable NestedClass));
2645 static assert( hasNested!(immutable NestedClass));
2647 static assert(!__traits(compiles, isNested!(NestedClass[1])));
2648 static assert( hasNested!(NestedClass[1]));
2649 static assert(!hasNested!(NestedClass[0]));
2651 static class A
2653 A a;
2655 static assert(!hasNested!A);
2659 /***
2660 * Get as a tuple the types of the fields of a struct, class, or union.
2661 * This consists of the fields that take up memory space,
2662 * excluding the hidden fields like the virtual function
2663 * table pointer or a context pointer for nested types.
2664 * If `T` isn't a struct, class, interface or union returns a tuple
2665 * with one element `T`.
2667 * History:
2668 * - Returned `AliasSeq!(Interface)` for interfaces prior to 2.097
2670 template Fields(T)
2672 import core.internal.traits : _Fields = Fields;
2673 alias Fields = _Fields!T;
2677 @safe unittest
2679 import std.meta : AliasSeq;
2680 struct S { int x; float y; }
2681 static assert(is(Fields!S == AliasSeq!(int, float)));
2685 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2687 alias FieldTypeTuple = Fields;
2689 @safe unittest
2691 static assert(is(FieldTypeTuple!int == AliasSeq!int));
2693 static struct StaticStruct1 { }
2694 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!()));
2696 static struct StaticStruct2 { int a, b; }
2697 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int)));
2699 int i;
2701 struct NestedStruct1 { void f() { ++i; } }
2702 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!()));
2704 struct NestedStruct2 { int a; void f() { ++i; } }
2705 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int));
2707 class NestedClass { int a; void f() { ++i; } }
2708 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int));
2710 static interface I {}
2711 static assert(is(Fields!I == AliasSeq!()));
2714 //Required for FieldNameTuple
2715 private enum NameOf(alias T) = T.stringof;
2718 * Get as an expression tuple the names of the fields of a struct, class, or
2719 * union. This consists of the fields that take up memory space, excluding the
2720 * hidden fields like the virtual function table pointer or a context pointer
2721 * for nested types.
2722 * Inherited fields (for classes) are not included.
2723 * If `T` isn't a struct, class, interface or union, an
2724 * expression tuple with an empty string is returned.
2726 * History:
2727 * - Returned `AliasSeq!""` for interfaces prior to 2.097
2729 template FieldNameTuple(T)
2731 import std.meta : staticMap;
2732 static if (is(T == struct) || is(T == union))
2733 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]);
2734 else static if (is(T == class) || is(T == interface))
2735 alias FieldNameTuple = staticMap!(NameOf, T.tupleof);
2736 else
2737 alias FieldNameTuple = AliasSeq!"";
2741 @safe unittest
2743 import std.meta : AliasSeq;
2744 struct S { int x; float y; }
2745 static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
2746 static assert(FieldNameTuple!int == AliasSeq!"");
2749 @safe unittest
2751 static assert(FieldNameTuple!int == AliasSeq!"");
2753 static struct StaticStruct1 { }
2754 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!()));
2756 static struct StaticStruct2 { int a, b; }
2757 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b"));
2759 static class StaticClass1 { }
2760 static assert(is(FieldNameTuple!StaticClass1 == AliasSeq!()));
2762 static class StaticClass2 : StaticClass1 { int a, b; }
2763 static assert(FieldNameTuple!StaticClass2 == AliasSeq!("a", "b"));
2765 static class StaticClass3 : StaticClass2 { int c; }
2766 static assert(FieldNameTuple!StaticClass3 == AliasSeq!("c"));
2768 int i;
2770 struct NestedStruct1 { void f() { ++i; } }
2771 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!()));
2773 struct NestedStruct2 { int a; void f() { ++i; } }
2774 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a");
2776 class NestedClass { int a; void f() { ++i; } }
2777 static assert(FieldNameTuple!NestedClass == AliasSeq!"a");
2779 interface I {}
2780 static assert(FieldNameTuple!I == AliasSeq!());
2784 /***
2785 Get the primitive types of the fields of a struct or class, in
2786 topological order.
2788 template RepresentationTypeTuple(T)
2790 static if (is(T == struct) || is(T == union) || is(T == class))
2792 alias RepresentationTypeTuple = staticMapMeta!(RepresentationTypeTupleImpl, FieldTypeTuple!T);
2794 else
2796 alias RepresentationTypeTuple = RepresentationTypeTupleImpl!T;
2801 @safe unittest
2803 struct S1 { int a; float b; }
2804 struct S2 { char[] a; union { S1 b; S1 * c; } }
2805 alias R = RepresentationTypeTuple!S2;
2806 assert(R.length == 4
2807 && is(R[0] == char[]) && is(R[1] == int)
2808 && is(R[2] == float) && is(R[3] == S1*));
2811 @safe unittest
2813 alias S1 = RepresentationTypeTuple!int;
2814 static assert(is(S1 == AliasSeq!int));
2816 struct S2 { int a; }
2817 struct S3 { int a; char b; }
2818 struct S4 { S1 a; int b; S3 c; }
2819 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int));
2820 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char)));
2821 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char)));
2823 struct S11 { int a; float b; }
2824 struct S21 { char[] a; union { S11 b; S11 * c; } }
2825 alias R = RepresentationTypeTuple!S21;
2826 assert(R.length == 4
2827 && is(R[0] == char[]) && is(R[1] == int)
2828 && is(R[2] == float) && is(R[3] == S11*));
2830 class C { int a; float b; }
2831 alias R1 = RepresentationTypeTuple!C;
2832 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float));
2834 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
2835 import std.typecons : Rebindable;
2837 struct S5 { int a; Rebindable!(immutable Object) b; }
2838 alias R2 = RepresentationTypeTuple!S5;
2839 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
2841 static assert(is(RepresentationTypeTuple!noreturn == AliasSeq!noreturn));
2844 @safe unittest
2846 struct VeryLargeType
2848 import std.format : format;
2849 import std.range : iota;
2851 static foreach (i; 500.iota)
2853 mixin(format!"int v%s;"(i));
2857 alias BigList = RepresentationTypeTuple!VeryLargeType;
2860 private template RepresentationTypeTupleImpl(T)
2862 import std.typecons : Rebindable;
2864 static if (is(immutable T == immutable Rebindable!R, R))
2866 alias RepresentationTypeTupleImpl
2867 = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R);
2869 else static if (is(T == struct) || is(T == union))
2871 // @@@BUG@@@ this should work
2872 //alias .RepresentationTypes!(T[0].tupleof)
2873 // RepresentationTypes;
2874 alias RepresentationTypeTupleImpl
2875 = staticMapMeta!(.RepresentationTypeTupleImpl, FieldTypeTuple!(T));
2877 else
2879 alias RepresentationTypeTupleImpl
2880 = AliasSeq!T;
2885 Statically evaluates to `true` if and only if `T`'s
2886 representation contains at least one field of pointer or array type.
2887 Members of class types are not considered raw pointers. Pointers to
2888 immutable objects are not considered raw aliasing.
2890 private template hasRawAliasing(T)
2892 enum hasRawAliasing = anySatisfy!(hasRawAliasingImpl, RepresentationTypeTuple!T);
2896 @safe unittest
2898 // simple types
2899 static assert(!hasRawAliasing!int);
2900 static assert( hasRawAliasing!(char*));
2901 // references aren't raw pointers
2902 static assert(!hasRawAliasing!Object);
2903 // built-in arrays do contain raw pointers
2904 static assert( hasRawAliasing!(int[]));
2905 // aggregate of simple types
2906 struct S1 { int a; double b; }
2907 static assert(!hasRawAliasing!S1);
2908 // indirect aggregation
2909 struct S2 { S1 a; double b; }
2910 static assert(!hasRawAliasing!S2);
2913 // https://issues.dlang.org/show_bug.cgi?id=19228
2914 @safe unittest
2916 static struct C
2918 int*[1] a;
2920 static assert(hasRawAliasing!C);
2923 @safe unittest
2925 // struct with a pointer member
2926 struct S3 { int a; double * b; }
2927 static assert( hasRawAliasing!S3);
2928 // struct with an indirect pointer member
2929 struct S4 { S3 a; double b; }
2930 static assert( hasRawAliasing!S4);
2931 struct S5 { int a; Object z; int c; }
2932 static assert( hasRawAliasing!S3);
2933 static assert( hasRawAliasing!S4);
2934 static assert(!hasRawAliasing!S5);
2936 union S6 { int a; int b; }
2937 union S7 { int a; int * b; }
2938 static assert(!hasRawAliasing!S6);
2939 static assert( hasRawAliasing!S7);
2941 static assert(!hasRawAliasing!(void delegate()));
2942 static assert(!hasRawAliasing!(void delegate() const));
2943 static assert(!hasRawAliasing!(void delegate() immutable));
2944 static assert(!hasRawAliasing!(void delegate() shared));
2945 static assert(!hasRawAliasing!(void delegate() shared const));
2946 static assert(!hasRawAliasing!(const(void delegate())));
2947 static assert(!hasRawAliasing!(immutable(void delegate())));
2949 struct S8 { void delegate() a; int b; Object c; }
2950 class S12 { typeof(S8.tupleof) a; }
2951 class S13 { typeof(S8.tupleof) a; int* b; }
2952 static assert(!hasRawAliasing!S8);
2953 static assert(!hasRawAliasing!S12);
2954 static assert( hasRawAliasing!S13);
2956 enum S9 { a }
2957 static assert(!hasRawAliasing!S9);
2959 // indirect members
2960 struct S10 { S7 a; int b; }
2961 struct S11 { S6 a; int b; }
2962 static assert( hasRawAliasing!S10);
2963 static assert(!hasRawAliasing!S11);
2965 static assert( hasRawAliasing!(int[string]));
2966 static assert(!hasRawAliasing!(immutable(int[string])));
2969 private template hasRawAliasingImpl(T)
2971 static if (is(T foo : U*, U) && !isFunctionPointer!T)
2972 enum hasRawAliasingImpl = !is(U == immutable);
2973 else static if (is(T foo : U[N], U, size_t N))
2974 // separate static ifs to avoid forward reference
2975 static if (is(U == class) || is(U == interface))
2976 enum hasRawAliasingImpl = false;
2977 else
2978 enum hasRawAliasingImpl = hasRawAliasingImpl!U;
2979 else static if (is(T foo : U[], U) && !isStaticArray!(T))
2980 enum hasRawAliasingImpl = !is(U == immutable);
2981 else static if (isAssociativeArray!(T))
2982 enum hasRawAliasingImpl = !is(T == immutable);
2983 else
2984 enum hasRawAliasingImpl = false;
2988 Statically evaluates to `true` if and only if `T`'s
2989 representation contains at least one non-shared field of pointer or
2990 array type. Members of class types are not considered raw pointers.
2991 Pointers to immutable objects are not considered raw aliasing.
2993 private template hasRawUnsharedAliasing(T)
2995 enum hasRawUnsharedAliasing = anySatisfy!(hasRawUnsharedAliasingImpl, RepresentationTypeTuple!T);
2999 @safe unittest
3001 // simple types
3002 static assert(!hasRawUnsharedAliasing!int);
3003 static assert( hasRawUnsharedAliasing!(char*));
3004 static assert(!hasRawUnsharedAliasing!(shared char*));
3005 // references aren't raw pointers
3006 static assert(!hasRawUnsharedAliasing!Object);
3007 // built-in arrays do contain raw pointers
3008 static assert( hasRawUnsharedAliasing!(int[]));
3009 static assert(!hasRawUnsharedAliasing!(shared int[]));
3010 // aggregate of simple types
3011 struct S1 { int a; double b; }
3012 static assert(!hasRawUnsharedAliasing!S1);
3013 // indirect aggregation
3014 struct S2 { S1 a; double b; }
3015 static assert(!hasRawUnsharedAliasing!S2);
3016 // struct with a pointer member
3017 struct S3 { int a; double * b; }
3018 static assert( hasRawUnsharedAliasing!S3);
3019 struct S4 { int a; shared double * b; }
3020 static assert(!hasRawUnsharedAliasing!S4);
3023 @safe unittest
3025 // struct with a pointer member
3026 struct S3 { int a; double * b; }
3027 static assert( hasRawUnsharedAliasing!S3);
3028 struct S4 { int a; shared double * b; }
3029 static assert(!hasRawUnsharedAliasing!S4);
3030 // struct with an indirect pointer member
3031 struct S5 { S3 a; double b; }
3032 static assert( hasRawUnsharedAliasing!S5);
3033 struct S6 { S4 a; double b; }
3034 static assert(!hasRawUnsharedAliasing!S6);
3035 struct S7 { int a; Object z; int c; }
3036 static assert( hasRawUnsharedAliasing!S5);
3037 static assert(!hasRawUnsharedAliasing!S6);
3038 static assert(!hasRawUnsharedAliasing!S7);
3040 union S8 { int a; int b; }
3041 union S9 { int a; int* b; }
3042 union S10 { int a; shared int* b; }
3043 static assert(!hasRawUnsharedAliasing!S8);
3044 static assert( hasRawUnsharedAliasing!S9);
3045 static assert(!hasRawUnsharedAliasing!S10);
3047 static assert(!hasRawUnsharedAliasing!(void delegate()));
3048 static assert(!hasRawUnsharedAliasing!(void delegate() const));
3049 static assert(!hasRawUnsharedAliasing!(void delegate() immutable));
3050 static assert(!hasRawUnsharedAliasing!(void delegate() shared));
3051 static assert(!hasRawUnsharedAliasing!(void delegate() shared const));
3052 static assert(!hasRawUnsharedAliasing!(const(void delegate())));
3053 static assert(!hasRawUnsharedAliasing!(const(void delegate() const)));
3054 static assert(!hasRawUnsharedAliasing!(const(void delegate() immutable)));
3055 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared)));
3056 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared const)));
3057 static assert(!hasRawUnsharedAliasing!(immutable(void delegate())));
3058 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() const)));
3059 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() immutable)));
3060 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared)));
3061 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared const)));
3062 static assert(!hasRawUnsharedAliasing!(shared(void delegate())));
3063 static assert(!hasRawUnsharedAliasing!(shared(void delegate() const)));
3064 static assert(!hasRawUnsharedAliasing!(shared(void delegate() immutable)));
3065 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared)));
3066 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared const)));
3067 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate()))));
3068 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() const))));
3069 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() immutable))));
3070 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared))));
3071 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared const))));
3072 static assert(!hasRawUnsharedAliasing!(void function()));
3074 enum S13 { a }
3075 static assert(!hasRawUnsharedAliasing!S13);
3077 // indirect members
3078 struct S14 { S9 a; int b; }
3079 struct S15 { S10 a; int b; }
3080 struct S16 { S6 a; int b; }
3081 static assert( hasRawUnsharedAliasing!S14);
3082 static assert(!hasRawUnsharedAliasing!S15);
3083 static assert(!hasRawUnsharedAliasing!S16);
3085 static assert( hasRawUnsharedAliasing!(int[string]));
3086 static assert(!hasRawUnsharedAliasing!(shared(int[string])));
3087 static assert(!hasRawUnsharedAliasing!(immutable(int[string])));
3089 struct S17
3091 void delegate() shared a;
3092 void delegate() immutable b;
3093 void delegate() shared const c;
3094 shared(void delegate()) d;
3095 shared(void delegate() shared) e;
3096 shared(void delegate() immutable) f;
3097 shared(void delegate() shared const) g;
3098 immutable(void delegate()) h;
3099 immutable(void delegate() shared) i;
3100 immutable(void delegate() immutable) j;
3101 immutable(void delegate() shared const) k;
3102 shared(const(void delegate())) l;
3103 shared(const(void delegate() shared)) m;
3104 shared(const(void delegate() immutable)) n;
3105 shared(const(void delegate() shared const)) o;
3107 struct S18 { typeof(S17.tupleof) a; void delegate() p; }
3108 struct S19 { typeof(S17.tupleof) a; Object p; }
3109 struct S20 { typeof(S17.tupleof) a; int* p; }
3110 class S21 { typeof(S17.tupleof) a; }
3111 class S22 { typeof(S17.tupleof) a; void delegate() p; }
3112 class S23 { typeof(S17.tupleof) a; Object p; }
3113 class S24 { typeof(S17.tupleof) a; int* p; }
3114 static assert(!hasRawUnsharedAliasing!S17);
3115 static assert(!hasRawUnsharedAliasing!(immutable(S17)));
3116 static assert(!hasRawUnsharedAliasing!(shared(S17)));
3117 static assert(!hasRawUnsharedAliasing!S18);
3118 static assert(!hasRawUnsharedAliasing!(immutable(S18)));
3119 static assert(!hasRawUnsharedAliasing!(shared(S18)));
3120 static assert(!hasRawUnsharedAliasing!S19);
3121 static assert(!hasRawUnsharedAliasing!(immutable(S19)));
3122 static assert(!hasRawUnsharedAliasing!(shared(S19)));
3123 static assert( hasRawUnsharedAliasing!S20);
3124 static assert(!hasRawUnsharedAliasing!(immutable(S20)));
3125 static assert(!hasRawUnsharedAliasing!(shared(S20)));
3126 static assert(!hasRawUnsharedAliasing!S21);
3127 static assert(!hasRawUnsharedAliasing!(immutable(S21)));
3128 static assert(!hasRawUnsharedAliasing!(shared(S21)));
3129 static assert(!hasRawUnsharedAliasing!S22);
3130 static assert(!hasRawUnsharedAliasing!(immutable(S22)));
3131 static assert(!hasRawUnsharedAliasing!(shared(S22)));
3132 static assert(!hasRawUnsharedAliasing!S23);
3133 static assert(!hasRawUnsharedAliasing!(immutable(S23)));
3134 static assert(!hasRawUnsharedAliasing!(shared(S23)));
3135 static assert( hasRawUnsharedAliasing!S24);
3136 static assert(!hasRawUnsharedAliasing!(immutable(S24)));
3137 static assert(!hasRawUnsharedAliasing!(shared(S24)));
3138 struct S25 {}
3139 class S26 {}
3140 interface S27 {}
3141 union S28 {}
3142 static assert(!hasRawUnsharedAliasing!S25);
3143 static assert(!hasRawUnsharedAliasing!S26);
3144 static assert(!hasRawUnsharedAliasing!S27);
3145 static assert(!hasRawUnsharedAliasing!S28);
3148 private template hasRawUnsharedAliasingImpl(T)
3150 static if (is(T foo : U*, U) && !isFunctionPointer!T)
3151 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3152 else static if (is(T foo : U[], U) && !isStaticArray!T)
3153 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared);
3154 else static if (isAssociativeArray!T)
3155 enum hasRawUnsharedAliasingImpl = !is(T == immutable) && !is(T == shared);
3156 else
3157 enum hasRawUnsharedAliasingImpl = false;
3161 Statically evaluates to `true` if and only if `T`'s
3162 representation includes at least one non-immutable object reference.
3165 private template hasObjects(T)
3167 static if (is(T == struct))
3169 enum hasObjects = anySatisfy!(.hasObjects, RepresentationTypeTuple!T);
3171 else
3173 enum hasObjects = (is(T == class) || is(T == interface)) && !is(T == immutable);
3178 Statically evaluates to `true` if and only if `T`'s
3179 representation includes at least one non-immutable non-shared object
3180 reference.
3182 private template hasUnsharedObjects(T)
3184 static if (is(T == struct))
3186 enum hasUnsharedObjects = anySatisfy!(.hasUnsharedObjects, RepresentationTypeTuple!T);
3188 else
3190 enum hasUnsharedObjects = (is(T == class) || is(T == interface)) &&
3191 !is(T == immutable) && !is(T == shared);
3196 Returns `true` if and only if `T`'s representation includes at
3197 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3198 is not immutable;) $(LI an array `U[]` and `U` is not
3199 immutable;) $(LI a reference to a class or interface type `C` and `C` is
3200 not immutable.) $(LI an associative array that is not immutable.)
3201 $(LI a delegate.))
3203 template hasAliasing(T...)
3205 enum hasAliasing = anySatisfy!(hasAliasingImpl, T);
3209 @safe unittest
3211 struct S1 { int a; Object b; }
3212 struct S2 { string a; }
3213 struct S3 { int a; immutable Object b; }
3214 struct S4 { float[3] vals; }
3215 static assert( hasAliasing!S1);
3216 static assert(!hasAliasing!S2);
3217 static assert(!hasAliasing!S3);
3218 static assert(!hasAliasing!S4);
3221 @safe unittest
3223 static assert( hasAliasing!(uint[uint]));
3224 static assert(!hasAliasing!(immutable(uint[uint])));
3225 static assert( hasAliasing!(void delegate()));
3226 static assert( hasAliasing!(void delegate() const));
3227 static assert(!hasAliasing!(void delegate() immutable));
3228 static assert( hasAliasing!(void delegate() shared));
3229 static assert( hasAliasing!(void delegate() shared const));
3230 static assert( hasAliasing!(const(void delegate())));
3231 static assert( hasAliasing!(const(void delegate() const)));
3232 static assert(!hasAliasing!(const(void delegate() immutable)));
3233 static assert( hasAliasing!(const(void delegate() shared)));
3234 static assert( hasAliasing!(const(void delegate() shared const)));
3235 static assert(!hasAliasing!(immutable(void delegate())));
3236 static assert(!hasAliasing!(immutable(void delegate() const)));
3237 static assert(!hasAliasing!(immutable(void delegate() immutable)));
3238 static assert(!hasAliasing!(immutable(void delegate() shared)));
3239 static assert(!hasAliasing!(immutable(void delegate() shared const)));
3240 static assert( hasAliasing!(shared(const(void delegate()))));
3241 static assert( hasAliasing!(shared(const(void delegate() const))));
3242 static assert(!hasAliasing!(shared(const(void delegate() immutable))));
3243 static assert( hasAliasing!(shared(const(void delegate() shared))));
3244 static assert( hasAliasing!(shared(const(void delegate() shared const))));
3245 static assert(!hasAliasing!(void function()));
3247 interface I;
3248 static assert( hasAliasing!I);
3250 import std.typecons : Rebindable;
3251 static assert( hasAliasing!(Rebindable!(const Object)));
3252 static assert(!hasAliasing!(Rebindable!(immutable Object)));
3253 static assert( hasAliasing!(Rebindable!(shared Object)));
3254 static assert( hasAliasing!(Rebindable!Object));
3256 struct S5
3258 void delegate() immutable b;
3259 shared(void delegate() immutable) f;
3260 immutable(void delegate() immutable) j;
3261 shared(const(void delegate() immutable)) n;
3263 struct S6 { typeof(S5.tupleof) a; void delegate() p; }
3264 static assert(!hasAliasing!S5);
3265 static assert( hasAliasing!S6);
3267 struct S7 { void delegate() a; int b; Object c; }
3268 class S8 { int a; int b; }
3269 class S9 { typeof(S8.tupleof) a; }
3270 class S10 { typeof(S8.tupleof) a; int* b; }
3271 static assert( hasAliasing!S7);
3272 static assert( hasAliasing!S8);
3273 static assert( hasAliasing!S9);
3274 static assert( hasAliasing!S10);
3275 struct S11 {}
3276 class S12 {}
3277 interface S13 {}
3278 union S14 {}
3279 static assert(!hasAliasing!S11);
3280 static assert( hasAliasing!S12);
3281 static assert( hasAliasing!S13);
3282 static assert(!hasAliasing!S14);
3284 class S15 { S15[1] a; }
3285 static assert( hasAliasing!S15);
3286 static assert(!hasAliasing!(immutable(S15)));
3288 static assert(!hasAliasing!noreturn);
3291 private template hasAliasingImpl(T)
3293 import std.typecons : Rebindable;
3295 static if (is(immutable T == immutable Rebindable!R, R))
3297 enum hasAliasingImpl = hasAliasingImpl!R;
3299 else
3301 template isAliasingDelegate(T)
3303 enum isAliasingDelegate = isDelegate!T
3304 && !is(T == immutable)
3305 && !is(FunctionTypeOf!T == immutable);
3307 enum hasAliasingImpl = hasRawAliasing!T || hasObjects!T ||
3308 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T);
3313 Returns `true` if and only if `T`'s representation includes at
3314 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an
3315 array `U[]`;) $(LI a reference to a class type `C`;)
3316 $(LI an associative array;) $(LI a delegate;)
3317 $(LI a [context pointer][isNested].))
3319 template hasIndirections(T)
3321 import core.internal.traits : _hasIndirections = hasIndirections;
3322 alias hasIndirections = _hasIndirections!T;
3326 @safe unittest
3328 static assert( hasIndirections!(int[string]));
3329 static assert( hasIndirections!(void delegate()));
3330 static assert( hasIndirections!(void delegate() immutable));
3331 static assert( hasIndirections!(immutable(void delegate())));
3332 static assert( hasIndirections!(immutable(void delegate() immutable)));
3334 static assert(!hasIndirections!(void function()));
3335 static assert( hasIndirections!(void*[1]));
3336 static assert(!hasIndirections!(byte[1]));
3339 @safe unittest
3341 // void static array hides actual type of bits, so "may have indirections".
3342 static assert( hasIndirections!(void[1]));
3343 interface I {}
3344 struct S1 {}
3345 struct S2 { int a; }
3346 struct S3 { int a; int b; }
3347 struct S4 { int a; int* b; }
3348 struct S5 { int a; Object b; }
3349 struct S6 { int a; string b; }
3350 struct S7 { int a; immutable Object b; }
3351 struct S8 { int a; immutable I b; }
3352 struct S9 { int a; void delegate() b; }
3353 struct S10 { int a; immutable(void delegate()) b; }
3354 struct S11 { int a; void delegate() immutable b; }
3355 struct S12 { int a; immutable(void delegate() immutable) b; }
3356 class S13 {}
3357 class S14 { int a; }
3358 class S15 { int a; int b; }
3359 class S16 { int a; Object b; }
3360 class S17 { string a; }
3361 class S18 { int a; immutable Object b; }
3362 class S19 { int a; immutable(void delegate() immutable) b; }
3363 union S20 {}
3364 union S21 { int a; }
3365 union S22 { int a; int b; }
3366 union S23 { int a; Object b; }
3367 union S24 { string a; }
3368 union S25 { int a; immutable Object b; }
3369 union S26 { int a; immutable(void delegate() immutable) b; }
3370 static assert( hasIndirections!I);
3371 static assert(!hasIndirections!S1);
3372 static assert(!hasIndirections!S2);
3373 static assert(!hasIndirections!S3);
3374 static assert( hasIndirections!S4);
3375 static assert( hasIndirections!S5);
3376 static assert( hasIndirections!S6);
3377 static assert( hasIndirections!S7);
3378 static assert( hasIndirections!S8);
3379 static assert( hasIndirections!S9);
3380 static assert( hasIndirections!S10);
3381 static assert( hasIndirections!S12);
3382 static assert( hasIndirections!S13);
3383 static assert( hasIndirections!S14);
3384 static assert( hasIndirections!S15);
3385 static assert( hasIndirections!S16);
3386 static assert( hasIndirections!S17);
3387 static assert( hasIndirections!S18);
3388 static assert( hasIndirections!S19);
3389 static assert(!hasIndirections!S20);
3390 static assert(!hasIndirections!S21);
3391 static assert(!hasIndirections!S22);
3392 static assert( hasIndirections!S23);
3393 static assert( hasIndirections!S24);
3394 static assert( hasIndirections!S25);
3395 static assert( hasIndirections!S26);
3396 int local;
3397 struct HasContextPointer { int opCall() { return ++local; } }
3398 static assert(hasIndirections!HasContextPointer);
3400 static assert(!hasIndirections!noreturn);
3403 // https://issues.dlang.org/show_bug.cgi?id=12000
3404 @safe unittest
3406 static struct S(T)
3408 static assert(hasIndirections!T);
3411 static class A(T)
3413 S!A a;
3416 A!int dummy;
3420 Returns `true` if and only if `T`'s representation includes at
3421 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3422 is not immutable or shared;) $(LI an array `U[]` and `U` is not
3423 immutable or shared;) $(LI a reference to a class type `C` and
3424 `C` is not immutable or shared.) $(LI an associative array that is not
3425 immutable or shared.) $(LI a delegate that is not shared.))
3428 template hasUnsharedAliasing(T...)
3430 enum hasUnsharedAliasing = anySatisfy!(hasUnsharedAliasingImpl, T);
3434 @safe unittest
3436 struct S1 { int a; Object b; }
3437 struct S2 { string a; }
3438 struct S3 { int a; immutable Object b; }
3439 static assert( hasUnsharedAliasing!S1);
3440 static assert(!hasUnsharedAliasing!S2);
3441 static assert(!hasUnsharedAliasing!S3);
3443 struct S4 { int a; shared Object b; }
3444 struct S5 { char[] a; }
3445 struct S6 { shared char[] b; }
3446 struct S7 { float[3] vals; }
3447 static assert(!hasUnsharedAliasing!S4);
3448 static assert( hasUnsharedAliasing!S5);
3449 static assert(!hasUnsharedAliasing!S6);
3450 static assert(!hasUnsharedAliasing!S7);
3453 @safe unittest
3455 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
3456 import std.typecons : Rebindable;
3457 struct S8 { int a; Rebindable!(immutable Object) b; }
3458 static assert(!hasUnsharedAliasing!S8);
3460 static assert( hasUnsharedAliasing!(uint[uint]));
3462 static assert( hasUnsharedAliasing!(void delegate()));
3463 static assert( hasUnsharedAliasing!(void delegate() const));
3464 static assert(!hasUnsharedAliasing!(void delegate() immutable));
3465 static assert(!hasUnsharedAliasing!(void delegate() shared));
3466 static assert(!hasUnsharedAliasing!(void delegate() shared const));
3469 @safe unittest
3471 import std.typecons : Rebindable;
3472 static assert( hasUnsharedAliasing!(const(void delegate())));
3473 static assert( hasUnsharedAliasing!(const(void delegate() const)));
3474 static assert(!hasUnsharedAliasing!(const(void delegate() immutable)));
3475 static assert(!hasUnsharedAliasing!(const(void delegate() shared)));
3476 static assert(!hasUnsharedAliasing!(const(void delegate() shared const)));
3477 static assert(!hasUnsharedAliasing!(immutable(void delegate())));
3478 static assert(!hasUnsharedAliasing!(immutable(void delegate() const)));
3479 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable)));
3480 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared)));
3481 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const)));
3482 static assert(!hasUnsharedAliasing!(shared(void delegate())));
3483 static assert(!hasUnsharedAliasing!(shared(void delegate() const)));
3484 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable)));
3485 static assert(!hasUnsharedAliasing!(shared(void delegate() shared)));
3486 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const)));
3487 static assert(!hasUnsharedAliasing!(shared(const(void delegate()))));
3488 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const))));
3489 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable))));
3490 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared))));
3491 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const))));
3492 static assert(!hasUnsharedAliasing!(void function()));
3494 interface I {}
3495 static assert(hasUnsharedAliasing!I);
3497 static assert( hasUnsharedAliasing!(Rebindable!(const Object)));
3498 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object)));
3499 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object)));
3500 static assert( hasUnsharedAliasing!(Rebindable!Object));
3502 /* https://issues.dlang.org/show_bug.cgi?id=6979 */
3503 static assert(!hasUnsharedAliasing!(int, shared(int)*));
3504 static assert( hasUnsharedAliasing!(int, int*));
3505 static assert( hasUnsharedAliasing!(int, const(int)[]));
3506 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object));
3507 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object)));
3508 static assert(!hasUnsharedAliasing!());
3510 struct S9
3512 void delegate() shared a;
3513 void delegate() immutable b;
3514 void delegate() shared const c;
3515 shared(void delegate()) d;
3516 shared(void delegate() shared) e;
3517 shared(void delegate() immutable) f;
3518 shared(void delegate() shared const) g;
3519 immutable(void delegate()) h;
3520 immutable(void delegate() shared) i;
3521 immutable(void delegate() immutable) j;
3522 immutable(void delegate() shared const) k;
3523 shared(const(void delegate())) l;
3524 shared(const(void delegate() shared)) m;
3525 shared(const(void delegate() immutable)) n;
3526 shared(const(void delegate() shared const)) o;
3528 struct S10 { typeof(S9.tupleof) a; void delegate() p; }
3529 struct S11 { typeof(S9.tupleof) a; Object p; }
3530 struct S12 { typeof(S9.tupleof) a; int* p; }
3531 class S13 { typeof(S9.tupleof) a; }
3532 class S14 { typeof(S9.tupleof) a; void delegate() p; }
3533 class S15 { typeof(S9.tupleof) a; Object p; }
3534 class S16 { typeof(S9.tupleof) a; int* p; }
3535 static assert(!hasUnsharedAliasing!S9);
3536 static assert(!hasUnsharedAliasing!(immutable(S9)));
3537 static assert(!hasUnsharedAliasing!(shared(S9)));
3538 static assert( hasUnsharedAliasing!S10);
3539 static assert(!hasUnsharedAliasing!(immutable(S10)));
3540 static assert(!hasUnsharedAliasing!(shared(S10)));
3541 static assert( hasUnsharedAliasing!S11);
3542 static assert(!hasUnsharedAliasing!(immutable(S11)));
3543 static assert(!hasUnsharedAliasing!(shared(S11)));
3544 static assert( hasUnsharedAliasing!S12);
3545 static assert(!hasUnsharedAliasing!(immutable(S12)));
3546 static assert(!hasUnsharedAliasing!(shared(S12)));
3547 static assert( hasUnsharedAliasing!S13);
3548 static assert(!hasUnsharedAliasing!(immutable(S13)));
3549 static assert(!hasUnsharedAliasing!(shared(S13)));
3550 static assert( hasUnsharedAliasing!S14);
3551 static assert(!hasUnsharedAliasing!(immutable(S14)));
3552 static assert(!hasUnsharedAliasing!(shared(S14)));
3553 static assert( hasUnsharedAliasing!S15);
3554 static assert(!hasUnsharedAliasing!(immutable(S15)));
3555 static assert(!hasUnsharedAliasing!(shared(S15)));
3556 static assert( hasUnsharedAliasing!S16);
3557 static assert(!hasUnsharedAliasing!(immutable(S16)));
3558 static assert(!hasUnsharedAliasing!(shared(S16)));
3559 struct S17 {}
3560 class S18 {}
3561 interface S19 {}
3562 union S20 {}
3563 static assert(!hasUnsharedAliasing!S17);
3564 static assert( hasUnsharedAliasing!S18);
3565 static assert( hasUnsharedAliasing!S19);
3566 static assert(!hasUnsharedAliasing!S20);
3568 static assert(!hasUnsharedAliasing!noreturn);
3571 private template hasUnsharedAliasingImpl(T)
3573 import std.typecons : Rebindable;
3575 static if (is(immutable T == immutable Rebindable!R, R))
3577 enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R;
3579 else
3581 template unsharedDelegate(T)
3583 enum bool unsharedDelegate = isDelegate!T
3584 && !is(T == shared)
3585 && !is(T == immutable)
3586 && !is(FunctionTypeOf!T == shared)
3587 && !is(FunctionTypeOf!T == immutable);
3590 enum hasUnsharedAliasingImpl =
3591 hasRawUnsharedAliasing!T ||
3592 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!T) ||
3593 hasUnsharedObjects!T;
3597 version (StdDdoc)
3600 True if `S` or any type embedded directly in the representation of `S`
3601 defines an elaborate copy constructor. Elaborate copy constructors are
3602 introduced by defining `this(this)` for a `struct`.
3604 Classes and unions never have elaborate copy constructors.
3606 template hasElaborateCopyConstructor(S)
3608 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3609 alias hasElaborateCopyConstructor = hasElabCCtor!(S);
3612 else
3614 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
3615 alias hasElaborateCopyConstructor = hasElabCCtor;
3619 @safe unittest
3621 static assert(!hasElaborateCopyConstructor!int);
3623 static struct S1 { }
3624 static struct S2 { this(this) {} }
3625 static struct S3 { S2 field; }
3626 static struct S4 { S3[1] field; }
3627 static struct S5 { S3[] field; }
3628 static struct S6 { S3[0] field; }
3629 static struct S7 { @disable this(); S3 field; }
3630 static assert(!hasElaborateCopyConstructor!S1);
3631 static assert( hasElaborateCopyConstructor!S2);
3632 static assert( hasElaborateCopyConstructor!(immutable S2));
3633 static assert( hasElaborateCopyConstructor!S3);
3634 static assert( hasElaborateCopyConstructor!(S3[1]));
3635 static assert(!hasElaborateCopyConstructor!(S3[0]));
3636 static assert( hasElaborateCopyConstructor!S4);
3637 static assert(!hasElaborateCopyConstructor!S5);
3638 static assert(!hasElaborateCopyConstructor!S6);
3639 static assert( hasElaborateCopyConstructor!S7);
3643 True if `S` or any type directly embedded in the representation of `S`
3644 defines an elaborate assignment. Elaborate assignments are introduced by
3645 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this)))
3646 for a `struct` or when there is a compiler-generated `opAssign`.
3648 A type `S` gets compiler-generated `opAssign` if it has
3649 an elaborate destructor.
3651 Classes and unions never have elaborate assignments.
3653 Note: Structs with (possibly nested) postblit operator(s) will have a
3654 hidden yet elaborate compiler generated assignment operator (unless
3655 explicitly disabled).
3657 template hasElaborateAssign(S)
3659 static if (isStaticArray!S && S.length)
3661 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0]));
3663 else static if (is(S == struct))
3665 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
3666 is(typeof(S.init.opAssign(lvalueOf!S))) ||
3667 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S);
3669 else
3671 enum bool hasElaborateAssign = false;
3676 @safe unittest
3678 static assert(!hasElaborateAssign!int);
3680 static struct S { void opAssign(S) {} }
3681 static assert( hasElaborateAssign!S);
3682 static assert(!hasElaborateAssign!(const(S)));
3684 static struct S1 { void opAssign(ref S1) {} }
3685 static struct S2 { void opAssign(int) {} }
3686 static struct S3 { S s; }
3687 static assert( hasElaborateAssign!S1);
3688 static assert(!hasElaborateAssign!S2);
3689 static assert( hasElaborateAssign!S3);
3690 static assert( hasElaborateAssign!(S3[1]));
3691 static assert(!hasElaborateAssign!(S3[0]));
3694 @safe unittest
3696 static struct S { void opAssign(S) {} }
3697 static struct S4
3699 void opAssign(U)(U u) {}
3700 @disable void opAssign(U)(ref U u);
3702 static assert( hasElaborateAssign!S4);
3704 static struct S41
3706 void opAssign(U)(ref U u) {}
3707 @disable void opAssign(U)(U u);
3709 static assert( hasElaborateAssign!S41);
3711 static struct S5 { @disable this(); this(int n){ s = S(); } S s; }
3712 static assert( hasElaborateAssign!S5);
3714 static struct S6 { this(this) {} }
3715 static struct S7 { this(this) {} @disable void opAssign(S7); }
3716 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} }
3717 static struct S9 { this(this) {} void opAssign(int) {} }
3718 static struct S10 { ~this() { } }
3719 static assert( hasElaborateAssign!S6);
3720 static assert(!hasElaborateAssign!S7);
3721 static assert(!hasElaborateAssign!S8);
3722 static assert( hasElaborateAssign!S9);
3723 static assert( hasElaborateAssign!S10);
3724 static struct SS6 { S6 s; }
3725 static struct SS7 { S7 s; }
3726 static struct SS8 { S8 s; }
3727 static struct SS9 { S9 s; }
3728 static assert( hasElaborateAssign!SS6);
3729 static assert(!hasElaborateAssign!SS7);
3730 static assert(!hasElaborateAssign!SS8);
3731 static assert( hasElaborateAssign!SS9);
3734 version (StdDdoc)
3737 True if `S` or any type directly embedded in the representation
3738 of `S` defines an elaborate destructor. Elaborate destructors
3739 are introduced by defining `~this()` for a $(D
3740 struct).
3742 Classes and unions never have elaborate destructors, even
3743 though classes may define `~this()`.
3745 template hasElaborateDestructor(S)
3747 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3748 alias hasElaborateDestructor = hasElabDest!(S);
3751 else
3753 import core.internal.traits : hasElabDest = hasElaborateDestructor;
3754 alias hasElaborateDestructor = hasElabDest;
3758 @safe unittest
3760 static assert(!hasElaborateDestructor!int);
3762 static struct S1 { }
3763 static struct S2 { ~this() {} }
3764 static struct S3 { S2 field; }
3765 static struct S4 { S3[1] field; }
3766 static struct S5 { S3[] field; }
3767 static struct S6 { S3[0] field; }
3768 static struct S7 { @disable this(); S3 field; }
3769 static assert(!hasElaborateDestructor!S1);
3770 static assert( hasElaborateDestructor!S2);
3771 static assert( hasElaborateDestructor!(immutable S2));
3772 static assert( hasElaborateDestructor!S3);
3773 static assert( hasElaborateDestructor!(S3[1]));
3774 static assert(!hasElaborateDestructor!(S3[0]));
3775 static assert( hasElaborateDestructor!S4);
3776 static assert(!hasElaborateDestructor!S5);
3777 static assert(!hasElaborateDestructor!S6);
3778 static assert( hasElaborateDestructor!S7);
3781 version (StdDdoc)
3784 True if `S` or any type embedded directly in the representation of `S`
3785 defines elaborate move semantics. Elaborate move semantics are
3786 introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
3788 Classes and unions never have elaborate move semantics.
3790 template hasElaborateMove(S)
3792 import core.internal.traits : hasElabMove = hasElaborateMove;
3793 alias hasElaborateMove = hasElabMove!(S);
3796 else
3798 import core.internal.traits : hasElabMove = hasElaborateMove;
3799 alias hasElaborateMove = hasElabMove;
3803 @safe unittest
3805 static assert(!hasElaborateMove!int);
3807 static struct S1 { }
3808 static struct S2 { void opPostMove(ref S2) {} }
3809 static struct S3 { void opPostMove(inout ref S3) inout {} }
3810 static struct S4 { void opPostMove(const ref S4) {} }
3811 static struct S5 { void opPostMove(S5) {} }
3812 static struct S6 { void opPostMove(int) {} }
3813 static struct S7 { S3[1] field; }
3814 static struct S8 { S3[] field; }
3815 static struct S9 { S3[0] field; }
3816 static struct S10 { @disable this(); S3 field; }
3817 static assert(!hasElaborateMove!S1);
3818 static assert( hasElaborateMove!S2);
3819 static assert( hasElaborateMove!S3);
3820 static assert( hasElaborateMove!(immutable S3));
3821 static assert( hasElaborateMove!S4);
3822 static assert(!hasElaborateMove!S5);
3823 static assert(!hasElaborateMove!S6);
3824 static assert( hasElaborateMove!S7);
3825 static assert(!hasElaborateMove!S8);
3826 static assert(!hasElaborateMove!S9);
3827 static assert( hasElaborateMove!S10);
3830 package alias Identity(alias A) = A;
3833 Yields `true` if and only if `T` is an aggregate that defines
3834 a symbol called `name`.
3836 enum hasMember(T, string name) = __traits(hasMember, T, name);
3839 @safe unittest
3841 static assert(!hasMember!(int, "blah"));
3842 struct S1 { int blah; }
3843 struct S2 { int blah(){ return 0; } }
3844 class C1 { int blah; }
3845 class C2 { int blah(){ return 0; } }
3846 static assert(hasMember!(S1, "blah"));
3847 static assert(hasMember!(S2, "blah"));
3848 static assert(hasMember!(C1, "blah"));
3849 static assert(hasMember!(C2, "blah"));
3852 @safe unittest
3854 // https://issues.dlang.org/show_bug.cgi?id=8321
3855 struct S {
3856 int x;
3857 void f(){}
3858 void t()(){}
3859 template T(){}
3861 struct R1(T) {
3862 T t;
3863 alias t this;
3865 struct R2(T) {
3866 T t;
3867 @property ref inout(T) payload() inout { return t; }
3868 alias t this;
3870 static assert(hasMember!(S, "x"));
3871 static assert(hasMember!(S, "f"));
3872 static assert(hasMember!(S, "t"));
3873 static assert(hasMember!(S, "T"));
3874 static assert(hasMember!(R1!S, "x"));
3875 static assert(hasMember!(R1!S, "f"));
3876 static assert(hasMember!(R1!S, "t"));
3877 static assert(hasMember!(R1!S, "T"));
3878 static assert(hasMember!(R2!S, "x"));
3879 static assert(hasMember!(R2!S, "f"));
3880 static assert(hasMember!(R2!S, "t"));
3881 static assert(hasMember!(R2!S, "T"));
3884 @safe unittest
3886 static struct S
3888 void opDispatch(string n, A)(A dummy) {}
3890 static assert(hasMember!(S, "foo"));
3894 * Whether the symbol represented by the string, member, exists and is a static member of T.
3896 * Params:
3897 * T = Type containing symbol `member`.
3898 * member = Name of symbol to test that resides in `T`.
3900 * Returns:
3901 * `true` iff `member` exists and is static.
3903 template hasStaticMember(T, string member)
3905 static if (__traits(hasMember, T, member))
3907 static if (isPointer!T)
3908 alias U = PointerTarget!T;
3909 else
3910 alias U = T;
3912 import std.meta : Alias;
3913 alias sym = Alias!(__traits(getMember, U, member));
3915 static if (__traits(getOverloads, U, member).length == 0)
3916 enum bool hasStaticMember = __traits(compiles, &sym);
3917 else
3918 enum bool hasStaticMember = __traits(isStaticFunction, sym);
3920 else
3922 enum bool hasStaticMember = false;
3927 @safe unittest
3929 static struct S
3931 static void sf() {}
3932 void f() {}
3934 static int si;
3935 int i;
3938 static assert( hasStaticMember!(S, "sf"));
3939 static assert(!hasStaticMember!(S, "f"));
3941 static assert( hasStaticMember!(S, "si"));
3942 static assert(!hasStaticMember!(S, "i"));
3944 static assert(!hasStaticMember!(S, "hello"));
3947 @safe unittest
3949 static struct S
3951 enum X = 10;
3952 enum Y
3954 i = 10
3956 struct S {}
3957 class C {}
3959 static int sx = 0;
3960 __gshared int gx = 0;
3962 Y y;
3963 static Y sy;
3965 static void f();
3966 static void f2() pure nothrow @nogc @safe;
3968 void g() shared;
3970 static void function() fp;
3971 __gshared void function() gfp;
3972 void function() fpm;
3974 void delegate() dm;
3975 static void delegate() sd;
3977 void m();
3978 void m2() const pure nothrow @nogc @safe;
3980 inout(int) iom() inout;
3981 static inout(int) iosf(inout int x);
3983 @property int p();
3984 static @property int sp();
3987 static class C
3989 enum X = 10;
3990 enum Y
3992 i = 10
3994 struct S {}
3995 class C {}
3997 static int sx = 0;
3998 __gshared int gx = 0;
4000 Y y;
4001 static Y sy;
4003 static void f();
4004 static void f2() pure nothrow @nogc @safe;
4006 void g() shared { }
4008 static void function() fp;
4009 __gshared void function() gfp;
4010 void function() fpm;
4012 void delegate() dm;
4013 static void delegate() sd;
4015 void m() {}
4016 final void m2() const pure nothrow @nogc @safe;
4018 inout(int) iom() inout { return 10; }
4019 static inout(int) iosf(inout int x);
4021 @property int p() { return 10; }
4022 static @property int sp();
4025 static assert(!hasStaticMember!(S, "na"));
4026 static assert(!hasStaticMember!(S, "X"));
4027 static assert(!hasStaticMember!(S, "Y"));
4028 static assert(!hasStaticMember!(S, "Y.i"));
4029 static assert(!hasStaticMember!(S, "S"));
4030 static assert(!hasStaticMember!(S, "C"));
4031 static assert( hasStaticMember!(S, "sx"));
4032 static assert( hasStaticMember!(S, "gx"));
4033 static assert(!hasStaticMember!(S, "y"));
4034 static assert( hasStaticMember!(S, "sy"));
4035 static assert( hasStaticMember!(S, "f"));
4036 static assert( hasStaticMember!(S, "f2"));
4037 static assert(!hasStaticMember!(S, "dm"));
4038 static assert( hasStaticMember!(S, "sd"));
4039 static assert(!hasStaticMember!(S, "g"));
4040 static assert( hasStaticMember!(S, "fp"));
4041 static assert( hasStaticMember!(S, "gfp"));
4042 static assert(!hasStaticMember!(S, "fpm"));
4043 static assert(!hasStaticMember!(S, "m"));
4044 static assert(!hasStaticMember!(S, "m2"));
4045 static assert(!hasStaticMember!(S, "iom"));
4046 static assert( hasStaticMember!(S, "iosf"));
4047 static assert(!hasStaticMember!(S, "p"));
4048 static assert( hasStaticMember!(S, "sp"));
4050 static assert(!hasStaticMember!(C, "na"));
4051 static assert(!hasStaticMember!(C, "X"));
4052 static assert(!hasStaticMember!(C, "Y"));
4053 static assert(!hasStaticMember!(C, "Y.i"));
4054 static assert(!hasStaticMember!(C, "S"));
4055 static assert(!hasStaticMember!(C, "C"));
4056 static assert( hasStaticMember!(C, "sx"));
4057 static assert( hasStaticMember!(C, "gx"));
4058 static assert(!hasStaticMember!(C, "y"));
4059 static assert( hasStaticMember!(C, "sy"));
4060 static assert( hasStaticMember!(C, "f"));
4061 static assert( hasStaticMember!(C, "f2"));
4062 static assert(!hasStaticMember!(C, "dm"));
4063 static assert( hasStaticMember!(C, "sd"));
4064 static assert(!hasStaticMember!(C, "g"));
4065 static assert( hasStaticMember!(C, "fp"));
4066 static assert( hasStaticMember!(C, "gfp"));
4067 static assert(!hasStaticMember!(C, "fpm"));
4068 static assert(!hasStaticMember!(C, "m"));
4069 static assert(!hasStaticMember!(C, "m2"));
4070 static assert(!hasStaticMember!(C, "iom"));
4071 static assert( hasStaticMember!(C, "iosf"));
4072 static assert(!hasStaticMember!(C, "p"));
4073 static assert( hasStaticMember!(C, "sp"));
4075 alias P = S*;
4076 static assert(!hasStaticMember!(P, "na"));
4077 static assert(!hasStaticMember!(P, "X"));
4078 static assert(!hasStaticMember!(P, "Y"));
4079 static assert(!hasStaticMember!(P, "Y.i"));
4080 static assert(!hasStaticMember!(P, "S"));
4081 static assert(!hasStaticMember!(P, "C"));
4082 static assert( hasStaticMember!(P, "sx"));
4083 static assert( hasStaticMember!(P, "gx"));
4084 static assert(!hasStaticMember!(P, "y"));
4085 static assert( hasStaticMember!(P, "sy"));
4086 static assert( hasStaticMember!(P, "f"));
4087 static assert( hasStaticMember!(P, "f2"));
4088 static assert(!hasStaticMember!(P, "dm"));
4089 static assert( hasStaticMember!(P, "sd"));
4090 static assert(!hasStaticMember!(P, "g"));
4091 static assert( hasStaticMember!(P, "fp"));
4092 static assert( hasStaticMember!(P, "gfp"));
4093 static assert(!hasStaticMember!(P, "fpm"));
4094 static assert(!hasStaticMember!(P, "m"));
4095 static assert(!hasStaticMember!(P, "m2"));
4096 static assert(!hasStaticMember!(P, "iom"));
4097 static assert( hasStaticMember!(P, "iosf"));
4098 static assert(!hasStaticMember!(P, "p"));
4099 static assert( hasStaticMember!(P, "sp"));
4103 Retrieves the members of an enumerated type `enum E`.
4105 Params:
4106 E = An enumerated type. `E` may have duplicated values.
4108 Returns:
4109 Static tuple composed of the members of the enumerated type `E`.
4110 The members are arranged in the same order as declared in `E`.
4111 The name of the enum can be found by querying the compiler for the
4112 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`.
4113 For enumerations with unique values, $(REF to, std,conv) can also be used.
4115 Note:
4116 An enum can have multiple members which have the same value. If you want
4117 to use EnumMembers to e.g. generate switch cases at compile-time,
4118 you should use the $(REF NoDuplicates, std,meta) template to avoid
4119 generating duplicate switch cases.
4121 Note:
4122 Returned values are strictly typed with `E`. Thus, the following code
4123 does not work without the explicit cast:
4124 --------------------
4125 enum E : int { a, b, c }
4126 int[] abc = cast(int[]) [ EnumMembers!E ];
4127 --------------------
4128 Cast is not necessary if the type of the variable is inferred. See the
4129 example below.
4131 template EnumMembers(E)
4132 if (is(E == enum))
4134 alias EnumMembers = AliasSeq!();
4135 static foreach (M; __traits(allMembers, E))
4136 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, M));
4139 /// Create an array of enumerated values
4140 @safe unittest
4142 enum Sqrts : real
4144 one = 1,
4145 two = 1.41421,
4146 three = 1.73205
4148 auto sqrts = [EnumMembers!Sqrts];
4149 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
4153 A generic function `rank(v)` in the following example uses this
4154 template for finding a member `e` in an enumerated type `E`.
4156 @safe unittest
4158 // Returns i if e is the i-th enumerator of E.
4159 static size_t rank(E)(E e)
4160 if (is(E == enum))
4162 static foreach (i, member; EnumMembers!E)
4164 if (e == member)
4165 return i;
4167 assert(0, "Not an enum member");
4170 enum Mode
4172 read = 1,
4173 write = 2,
4174 map = 4
4176 assert(rank(Mode.read) == 0);
4177 assert(rank(Mode.write) == 1);
4178 assert(rank(Mode.map) == 2);
4182 Use EnumMembers to generate a switch statement using static foreach.
4185 @safe unittest
4187 import std.conv : to;
4188 class FooClass
4190 string calledMethod;
4191 void foo() @safe { calledMethod = "foo"; }
4192 void bar() @safe { calledMethod = "bar"; }
4193 void baz() @safe { calledMethod = "baz"; }
4196 enum FooEnum { foo, bar, baz }
4198 auto var = FooEnum.bar;
4199 auto fooObj = new FooClass();
4200 s: final switch (var)
4202 static foreach (member; EnumMembers!FooEnum)
4204 case member: // Generate a case for each enum value.
4205 // Call fooObj.{name of enum value}().
4206 __traits(getMember, fooObj, to!string(member))();
4207 break s;
4210 // As we pass in FooEnum.bar, the bar() method gets called.
4211 assert(fooObj.calledMethod == "bar");
4214 @safe unittest
4216 enum A { a }
4217 static assert([ EnumMembers!A ] == [ A.a ]);
4218 enum B { a, b, c, d, e }
4219 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]);
4222 @safe unittest // typed enums
4224 enum A : string { a = "alpha", b = "beta" }
4225 static assert([ EnumMembers!A ] == [ A.a, A.b ]);
4227 static struct S
4229 int value;
4230 int opCmp(S rhs) const nothrow { return value - rhs.value; }
4232 enum B : S { a = S(1), b = S(2), c = S(3) }
4233 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]);
4236 @safe unittest // duplicated values
4238 enum A
4240 a = 0, b = 0,
4241 c = 1, d = 1, e
4243 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]);
4246 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
4247 @safe unittest
4249 string genEnum()
4251 string result = "enum TLAs {";
4252 foreach (c0; '0'..'2'+1)
4253 foreach (c1; '0'..'9'+1)
4254 foreach (c2; '0'..'9'+1)
4255 foreach (c3; '0'..'9'+1)
4257 result ~= '_';
4258 result ~= c0;
4259 result ~= c1;
4260 result ~= c2;
4261 result ~= c3;
4262 result ~= ',';
4264 result ~= '}';
4265 return result;
4267 mixin(genEnum);
4268 static assert(EnumMembers!TLAs[0] == TLAs._0000);
4269 static assert(EnumMembers!TLAs[$-1] == TLAs._2999);
4272 @safe unittest
4274 enum E { member, a = 0, b = 0 }
4275 static assert(__traits(identifier, EnumMembers!E[0]) == "member");
4276 static assert(__traits(identifier, EnumMembers!E[1]) == "a");
4277 static assert(__traits(identifier, EnumMembers!E[2]) == "b");
4281 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4282 // Classes and Interfaces
4283 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4285 /***
4286 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
4287 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
4288 * the empty type tuple.
4290 template BaseTypeTuple(A)
4292 static if (is(A P == super))
4293 alias BaseTypeTuple = P;
4294 else
4295 static assert(0, "argument is not a class or interface");
4299 @safe unittest
4301 import std.meta : AliasSeq;
4303 interface I1 { }
4304 interface I2 { }
4305 interface I12 : I1, I2 { }
4306 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));
4308 interface I3 : I1 { }
4309 interface I123 : I1, I2, I3 { }
4310 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));
4313 @safe unittest
4315 interface I1 { }
4316 interface I2 { }
4317 class A { }
4318 class C : A, I1, I2 { }
4320 alias TL = BaseTypeTuple!C;
4321 assert(TL.length == 3);
4322 assert(is (TL[0] == A));
4323 assert(is (TL[1] == I1));
4324 assert(is (TL[2] == I2));
4326 assert(BaseTypeTuple!Object.length == 0);
4330 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4331 * in decreasing order. Interfaces are not included. $(D_PARAM
4332 * BaseClassesTuple!Object) yields the empty type tuple.
4334 template BaseClassesTuple(T)
4335 if (is(T == class))
4337 static if (is(T == Object))
4339 alias BaseClassesTuple = AliasSeq!();
4341 else static if (is(BaseTypeTuple!T[0] == Object))
4343 alias BaseClassesTuple = AliasSeq!Object;
4345 else static if (!is(BaseTypeTuple!T[0] == Object) && !is(BaseTypeTuple!T[0] == class))
4347 alias BaseClassesTuple = AliasSeq!();
4349 else
4351 alias BaseClassesTuple =
4352 AliasSeq!(BaseTypeTuple!T[0],
4353 BaseClassesTuple!(BaseTypeTuple!T[0]));
4358 @safe unittest
4360 import std.meta : AliasSeq;
4362 class C1 { }
4363 class C2 : C1 { }
4364 class C3 : C2 { }
4365 static assert(!BaseClassesTuple!Object.length);
4366 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
4367 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
4368 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));
4371 // https://issues.dlang.org/show_bug.cgi?id=17276
4372 @safe unittest
4374 extern (C++) static interface Ext
4376 void someext();
4379 extern (C++) static class E : Ext
4381 void someext() {}
4384 alias BaseClassesWithNoObject = BaseClassesTuple!E;
4387 @safe unittest
4389 struct S { }
4390 static assert(!__traits(compiles, BaseClassesTuple!S));
4391 interface I { }
4392 static assert(!__traits(compiles, BaseClassesTuple!I));
4393 class C4 : I { }
4394 class C5 : C4, I { }
4395 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object)));
4399 Params:
4400 T = The `class` or `interface` to search.
4402 Returns:
4403 $(REF AliasSeq,std,meta) of all interfaces directly or
4404 indirectly inherited by this class or interface. Interfaces
4405 do not repeat if multiply implemented.
4407 `InterfacesTuple!Object` yields an empty `AliasSeq`.
4409 template InterfacesTuple(T)
4411 import std.meta : NoDuplicates;
4412 template Flatten(H, T...)
4414 static if (T.length)
4416 alias Flatten = AliasSeq!(Flatten!H, Flatten!T);
4418 else
4420 static if (is(H == interface))
4421 alias Flatten = AliasSeq!(H, InterfacesTuple!H);
4422 else
4423 alias Flatten = InterfacesTuple!H;
4427 static if (is(T S == super) && S.length)
4428 alias InterfacesTuple = NoDuplicates!(Flatten!S);
4429 else
4430 alias InterfacesTuple = AliasSeq!();
4434 @safe unittest
4436 interface I1 {}
4437 interface I2 {}
4438 class A : I1, I2 {}
4439 class B : A, I1 {}
4440 class C : B {}
4442 alias TL = InterfacesTuple!C;
4443 static assert(is(TL[0] == I1) && is(TL[1] == I2));
4446 @safe unittest
4448 interface Iaa {}
4449 interface Iab {}
4450 interface Iba {}
4451 interface Ibb {}
4452 interface Ia : Iaa, Iab {}
4453 interface Ib : Iba, Ibb {}
4454 interface I : Ia, Ib {}
4455 interface J {}
4456 class B2 : J {}
4457 class C2 : B2, Ia, Ib {}
4458 static assert(is(InterfacesTuple!I ==
4459 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb)));
4460 static assert(is(InterfacesTuple!C2 ==
4461 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb)));
4466 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4467 * T), in decreasing order, followed by $(D_PARAM T)'s
4468 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4469 * empty type tuple.
4471 alias TransitiveBaseTypeTuple(T) = AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
4474 @safe unittest
4476 interface J1 {}
4477 interface J2 {}
4478 class B1 {}
4479 class B2 : B1, J1, J2 {}
4480 class B3 : B2, J1 {}
4481 alias TL = TransitiveBaseTypeTuple!B3;
4482 assert(TL.length == 5);
4483 assert(is (TL[0] == B2));
4484 assert(is (TL[1] == B1));
4485 assert(is (TL[2] == Object));
4486 assert(is (TL[3] == J1));
4487 assert(is (TL[4] == J2));
4489 assert(TransitiveBaseTypeTuple!Object.length == 0);
4494 Returns a tuple of non-static functions with the name `name` declared in the
4495 class or interface `C`. Covariant duplicates are shrunk into the most
4496 derived one.
4498 template MemberFunctionsTuple(C, string name)
4499 if (is(C == class) || is(C == interface))
4501 static if (__traits(hasMember, C, name))
4504 * First, collect all overloads in the class hierarchy.
4506 template CollectOverloads(Node)
4508 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
4510 // Get all overloads in sight (not hidden).
4511 alias inSight = __traits(getVirtualFunctions, Node, name);
4513 // And collect all overloads in ancestor classes to reveal hidden
4514 // methods. The result may contain duplicates.
4515 template walkThru(Parents...)
4517 static if (Parents.length > 0)
4518 alias walkThru = AliasSeq!(
4519 CollectOverloads!(Parents[0]),
4520 walkThru!(Parents[1 .. $])
4522 else
4523 alias walkThru = AliasSeq!();
4526 static if (is(Node Parents == super))
4527 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents);
4528 else
4529 alias CollectOverloads = AliasSeq!inSight;
4531 else
4532 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy
4535 static if (name == "__ctor" || name == "__dtor")
4536 alias overloads = AliasSeq!(__traits(getOverloads, C, name));
4537 else
4538 // duplicates in this tuple will be removed by shrink()
4539 alias overloads = CollectOverloads!C;
4541 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4542 // shrinkOne!args[1..$] = non-covariant others
4543 template shrinkOne(/+ alias target, rest... +/ args...)
4545 import std.meta : AliasSeq;
4546 alias target = args[0 .. 1]; // prevent property functions from being evaluated
4547 alias rest = args[1 .. $];
4549 static if (rest.length > 0)
4551 alias Target = FunctionTypeOf!target;
4552 alias Rest0 = FunctionTypeOf!(rest[0]);
4554 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target))
4556 // One of these overrides the other. Choose the one from the most derived parent.
4557 static if (is(__traits(parent, target) : __traits(parent, rest[0])))
4558 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4559 else
4560 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4562 else static if (isCovariantWith!(Target, Rest0))
4563 // target overrides rest[0] -- erase rest[0].
4564 alias shrinkOne = shrinkOne!(target, rest[1 .. $]);
4565 else static if (isCovariantWith!(Rest0, Target))
4566 // rest[0] overrides target -- erase target.
4567 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]);
4568 else
4569 // target and rest[0] are distinct.
4570 alias shrinkOne = AliasSeq!(
4571 shrinkOne!(target, rest[1 .. $]),
4572 rest[0] // keep
4575 else
4576 alias shrinkOne = AliasSeq!target; // done
4580 * Now shrink covariant overloads into one.
4582 template shrink(overloads...)
4584 static if (overloads.length > 0)
4586 alias temp = shrinkOne!overloads;
4587 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $]));
4589 else
4590 alias shrink = AliasSeq!(); // done
4593 // done.
4594 alias MemberFunctionsTuple = shrink!overloads;
4596 else
4597 alias MemberFunctionsTuple = AliasSeq!();
4601 @safe unittest
4603 interface I { I foo(); }
4604 class B
4606 real foo(real v) { return v; }
4608 class C : B, I
4610 override C foo() { return this; } // covariant overriding of I.foo()
4612 alias foos = MemberFunctionsTuple!(C, "foo");
4613 static assert(foos.length == 2);
4614 static assert(__traits(isSame, foos[0], C.foo));
4615 static assert(__traits(isSame, foos[1], B.foo));
4618 // https://issues.dlang.org/show_bug.cgi?id=15920
4619 @safe unittest
4621 import std.meta : AliasSeq;
4622 class A
4624 void f(){}
4625 void f(int){}
4627 class B : A
4629 override void f(){}
4630 override void f(int){}
4632 alias fs = MemberFunctionsTuple!(B, "f");
4633 alias bfs = __traits(getOverloads, B, "f");
4634 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1]));
4635 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1]));
4638 // https://issues.dlang.org/show_bug.cgi?id=8388
4639 @safe unittest
4641 class C
4643 this() {}
4644 this(int i) {}
4645 this(int i, float j) {}
4646 this(string s) {}
4649 Commented out, because this causes a cyclic dependency
4650 between module constructors/destructors error. Might
4651 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */
4652 // static this() {}
4654 ~this() {}
4657 class D : C
4659 this() {}
4660 ~this() {}
4663 alias test_ctor = MemberFunctionsTuple!(C, "__ctor");
4664 assert(test_ctor.length == 4);
4665 alias test_dtor = MemberFunctionsTuple!(C, "__dtor");
4666 assert(test_dtor.length == 1);
4667 alias test2_ctor = MemberFunctionsTuple!(D, "__ctor");
4668 assert(test2_ctor.length == 1);
4669 alias test2_dtor = MemberFunctionsTuple!(D, "__dtor");
4670 assert(test2_dtor.length == 1);
4673 @safe unittest
4675 interface I { I test(); }
4676 interface J : I { J test(); }
4677 interface K { K test(int); }
4678 class B : I, K
4680 K test(int) { return this; }
4681 B test() { return this; }
4682 static void test(string) { }
4684 class C : B, J
4686 override C test() { return this; }
4688 alias test =MemberFunctionsTuple!(C, "test");
4689 static assert(test.length == 2);
4690 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test)));
4691 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test)));
4692 alias noexist = MemberFunctionsTuple!(C, "noexist");
4693 static assert(noexist.length == 0);
4695 interface L { int prop() @property; }
4696 alias prop = MemberFunctionsTuple!(L, "prop");
4697 static assert(prop.length == 1);
4699 interface Test_I
4701 void foo();
4702 void foo(int);
4703 void foo(int, int);
4705 interface Test : Test_I {}
4706 alias Test_foo = MemberFunctionsTuple!(Test, "foo");
4707 static assert(Test_foo.length == 3);
4708 static assert(is(typeof(&Test_foo[0]) == void function()));
4709 static assert(is(typeof(&Test_foo[2]) == void function(int)));
4710 static assert(is(typeof(&Test_foo[1]) == void function(int, int)));
4715 Returns an alias to the template that `T` is an instance of.
4716 It will return `void` if a symbol without a template is given.
4718 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
4720 /// ditto
4721 alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
4723 /// ditto
4724 alias TemplateOf(T) = void;
4727 @safe unittest
4729 struct Foo(T, U) {}
4730 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4733 @safe unittest
4735 template Foo1(A) {}
4736 template Foo2(A, B) {}
4737 template Foo3(alias A) {}
4738 template Foo4(string A) {}
4739 struct Foo5(A) {}
4740 struct Foo6(A, B) {}
4741 struct Foo7(alias A) {}
4742 template Foo8(A) { template Foo9(B) {} }
4743 template Foo10() {}
4745 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4746 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4747 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4748 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4749 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4750 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4751 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4752 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4753 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4756 // https://issues.dlang.org/show_bug.cgi?id=18214
4757 @safe unittest
4759 static assert(is(TemplateOf!(int[]) == void));
4760 static assert(is(TemplateOf!bool == void));
4764 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4766 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4768 /// ditto
4769 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4772 @safe unittest
4774 import std.meta : AliasSeq;
4776 struct Foo(T, U) {}
4777 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4780 @safe unittest
4782 template Foo1(A) {}
4783 template Foo2(A, B) {}
4784 template Foo3(alias A) {}
4785 template Foo4(string A) {}
4786 struct Foo5(A) {}
4787 struct Foo6(A, B) {}
4788 struct Foo7(alias A) {}
4789 template Foo8(A) { template Foo9(B) {} }
4790 template Foo10() {}
4792 enum x = 123;
4793 enum y = "123";
4794 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4795 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4796 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4797 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4798 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4799 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4800 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4801 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4802 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4805 // Returns the largest alignment in a type tuple.
4806 package enum maxAlignment(U...) =
4808 size_t result = U[0].alignof;
4809 static foreach (T; U[1 .. $])
4810 if (result < T.alignof)
4811 result = T.alignof;
4812 return result;
4813 }();
4816 Returns class instance alignment.
4818 template classInstanceAlignment(T)
4819 if (is(T == class))
4821 alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof));
4825 @safe unittest
4827 class A { byte b; }
4828 class B { long l; }
4830 // As class instance always has a hidden pointer
4831 static assert(classInstanceAlignment!A == (void*).alignof);
4832 static assert(classInstanceAlignment!B == long.alignof);
4836 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4837 // Type Conversion
4838 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4841 Get the type that all types can be implicitly converted to. Useful
4842 e.g. in figuring out an array type from a bunch of initializing
4843 values. Returns $(D_PARAM void) if passed an empty list, or if the
4844 types have no common type.
4846 template CommonType(T...)
4848 static if (T.length == 1)
4849 alias CommonType = typeof(T[0].init);
4850 else static if (is(typeof(true ? T[0].init : T[1].init) U))
4851 alias CommonType = CommonType!(U, T[2 .. $]);
4852 else
4853 alias CommonType = void;
4857 @safe unittest
4859 alias X = CommonType!(int, long, short);
4860 assert(is(X == long));
4861 alias Y = CommonType!(int, char[], short);
4862 assert(is(Y == void));
4866 @safe unittest
4868 static assert(is(CommonType!(3) == int));
4869 static assert(is(CommonType!(double, 4, float) == double));
4870 static assert(is(CommonType!(string, char[]) == const(char)[]));
4871 static assert(is(CommonType!(3, 3U) == uint));
4872 static assert(is(CommonType!(double, int) == double));
4877 Params:
4878 T = The type to check
4880 Returns:
4881 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4882 conversion `T`.
4884 If `T` is a class derived from `Object`, the result of
4885 $(LREF TransitiveBaseTypeTuple) is returned.
4887 If the type is not a built-in value type or a class derived from
4888 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4890 See_Also:
4891 $(LREF isImplicitlyConvertible)
4893 template AllImplicitConversionTargets(T)
4895 static if (is(T == bool))
4896 alias AllImplicitConversionTargets =
4897 AliasSeq!(byte, AllImplicitConversionTargets!byte);
4898 else static if (is(T == byte))
4899 alias AllImplicitConversionTargets =
4900 AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4901 else static if (is(T == ubyte))
4902 alias AllImplicitConversionTargets =
4903 AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4904 else static if (is(T == short))
4905 alias AllImplicitConversionTargets =
4906 AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4907 else static if (is(T == ushort))
4908 alias AllImplicitConversionTargets =
4909 AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4910 else static if (is(T == int))
4911 alias AllImplicitConversionTargets =
4912 AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4913 else static if (is(T == uint))
4914 alias AllImplicitConversionTargets =
4915 AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4916 else static if (is(T == long))
4917 alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4918 else static if (is(T == ulong))
4919 alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4920 else static if (is(T == float))
4921 alias AllImplicitConversionTargets = AliasSeq!(double, real);
4922 else static if (is(T == double))
4923 alias AllImplicitConversionTargets = AliasSeq!(float, real);
4924 else static if (is(T == real))
4925 alias AllImplicitConversionTargets = AliasSeq!(float, double);
4926 else static if (is(T == char))
4927 alias AllImplicitConversionTargets =
4928 AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4929 else static if (is(T == wchar))
4930 alias AllImplicitConversionTargets =
4931 AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4932 else static if (is(T == dchar))
4933 alias AllImplicitConversionTargets =
4934 AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4935 else static if (is(T == class))
4936 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4937 else static if (is(T == interface))
4938 alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4939 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4941 static if (is(typeof(T.init[0]) == shared))
4942 alias AllImplicitConversionTargets =
4943 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4944 else
4945 alias AllImplicitConversionTargets =
4946 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4948 else static if (is(T : void*) && !is(T == void*))
4949 alias AllImplicitConversionTargets = AliasSeq!(void*);
4950 else static if (is(cent) && is(T == cent))
4951 alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4952 else static if (is(ucent) && is(T == ucent))
4953 alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4954 else
4955 alias AllImplicitConversionTargets = AliasSeq!();
4959 @safe unittest
4961 import std.meta : AliasSeq;
4963 static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4964 static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4965 static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4966 static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4968 static assert(is(AllImplicitConversionTargets!(char) ==
4969 AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4970 ulong, float, double, real)
4972 static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4973 short, ushort, dchar, int, uint, long, ulong, float, double, real
4974 )));
4975 static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
4976 int, uint, long, ulong, float, double, real
4977 )));
4979 static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
4980 static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
4982 interface A {}
4983 interface B {}
4984 class C : A, B {}
4986 static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
4987 static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
4988 static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
4989 immutable Object, immutable A, immutable B
4990 )));
4992 interface I : A, B {}
4994 static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
4995 static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
4996 static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
4997 immutable A, immutable B
4998 )));
5001 @safe unittest
5003 static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5004 static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5005 static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5010 Params:
5011 T = The type to check
5013 Warning:
5014 This template is considered out-dated. It will be removed from
5015 Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5017 Returns:
5018 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5019 conversion `T`.
5021 If `T` is a class derived from `Object`, the result of
5022 $(LREF TransitiveBaseTypeTuple) is returned.
5024 If the type is not a built-in value type or a class derived from
5025 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5027 Note:
5028 The possible targets are computed more conservatively than the
5029 language allows, eliminating all dangerous conversions. For example,
5030 `ImplicitConversionTargets!double` does not include `float`.
5032 See_Also:
5033 $(LREF isImplicitlyConvertible)
5035 // @@@DEPRECATED_[2.107.0]@@@
5036 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5037 ~ "and will be removed in 2.107.0")
5038 template ImplicitConversionTargets(T)
5040 static if (is(T == bool))
5041 alias ImplicitConversionTargets =
5042 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5043 float, double, real, char, wchar, dchar);
5044 else static if (is(T == byte))
5045 alias ImplicitConversionTargets =
5046 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5047 float, double, real, char, wchar, dchar);
5048 else static if (is(T == ubyte))
5049 alias ImplicitConversionTargets =
5050 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5051 float, double, real, char, wchar, dchar);
5052 else static if (is(T == short))
5053 alias ImplicitConversionTargets =
5054 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5055 else static if (is(T == ushort))
5056 alias ImplicitConversionTargets =
5057 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5058 else static if (is(T == int))
5059 alias ImplicitConversionTargets =
5060 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5061 else static if (is(T == uint))
5062 alias ImplicitConversionTargets =
5063 AliasSeq!(long, ulong, CentTypeList, float, double, real);
5064 else static if (is(T == long))
5065 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5066 else static if (is(T == ulong))
5067 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5068 else static if (is(cent) && is(T == cent))
5069 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5070 else static if (is(ucent) && is(T == ucent))
5071 alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5072 else static if (is(T == float))
5073 alias ImplicitConversionTargets = AliasSeq!(double, real);
5074 else static if (is(T == double))
5075 alias ImplicitConversionTargets = AliasSeq!real;
5076 else static if (is(T == char))
5077 alias ImplicitConversionTargets =
5078 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5079 int, uint, long, ulong, CentTypeList, float, double, real);
5080 else static if (is(T == wchar))
5081 alias ImplicitConversionTargets =
5082 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5083 float, double, real);
5084 else static if (is(T == dchar))
5085 alias ImplicitConversionTargets =
5086 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5087 else static if (is(T : typeof(null)))
5088 alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5089 else static if (is(T == class))
5090 alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5091 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5093 static if (is(typeof(T.init[0]) == shared))
5094 alias ImplicitConversionTargets =
5095 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5096 else
5097 alias ImplicitConversionTargets =
5098 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5100 else static if (is(T : void*))
5101 alias ImplicitConversionTargets = AliasSeq!(void*);
5102 else
5103 alias ImplicitConversionTargets = AliasSeq!();
5106 deprecated @safe unittest
5108 import std.meta : AliasSeq;
5110 static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5111 static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5112 static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5113 static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5115 static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5116 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5117 )));
5118 static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5119 dchar, short, ushort, int, uint, long, ulong, float, double, real
5120 )));
5121 static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5122 int, uint, long, ulong, float, double, real
5123 )));
5125 static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5126 static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5128 interface A {}
5129 interface B {}
5130 class C : A, B {}
5132 static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5133 static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5134 static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5135 immutable Object, immutable A, immutable B
5136 )));
5139 deprecated @safe unittest
5141 static assert(is(ImplicitConversionTargets!(double)[0] == real));
5142 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5146 Is `From` implicitly convertible to `To`?
5148 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5151 @safe unittest
5153 static assert( isImplicitlyConvertible!(immutable(char), char));
5154 static assert( isImplicitlyConvertible!(const(char), char));
5155 static assert( isImplicitlyConvertible!(char, wchar));
5156 static assert(!isImplicitlyConvertible!(wchar, char));
5158 static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5159 static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5160 static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5162 static assert(!isImplicitlyConvertible!(const(char)[], string));
5163 static assert( isImplicitlyConvertible!(string, const(char)[]));
5167 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5168 type `Lhs`.
5170 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5172 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5174 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5177 @safe unittest
5179 static assert( isAssignable!(long, int));
5180 static assert(!isAssignable!(int, long));
5181 static assert( isAssignable!(const(char)[], string));
5182 static assert(!isAssignable!(string, char[]));
5184 // int is assignable to int
5185 static assert( isAssignable!int);
5187 // immutable int is not assignable to immutable int
5188 static assert(!isAssignable!(immutable int));
5192 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5193 type `Lhs`
5195 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5198 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5199 type `Lhs`
5201 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5203 @safe unittest
5205 static assert(!isAssignable!(immutable int, int));
5206 static assert( isAssignable!(int, immutable int));
5208 static assert(!isAssignable!(inout int, int));
5209 static assert( isAssignable!(int, inout int));
5210 static assert(!isAssignable!(inout int));
5212 static assert( isAssignable!(shared int, int));
5213 static assert( isAssignable!(int, shared int));
5214 static assert( isAssignable!(shared int));
5216 static assert( isAssignable!(void[1], void[1]));
5218 struct S { @disable this(); this(int n){} }
5219 static assert( isAssignable!(S, S));
5221 struct S2 { this(int n){} }
5222 static assert( isAssignable!(S2, S2));
5223 static assert(!isAssignable!(S2, int));
5225 struct S3 { @disable void opAssign(); }
5226 static assert( isAssignable!(S3, S3));
5228 struct S3X { @disable void opAssign(S3X); }
5229 static assert(!isAssignable!(S3X, S3X));
5231 struct S4 { void opAssign(int); }
5232 static assert( isAssignable!(S4, S4));
5233 static assert( isAssignable!(S4, int));
5234 static assert( isAssignable!(S4, immutable int));
5236 struct S5 { @disable this(); @disable this(this); }
5237 // https://issues.dlang.org/show_bug.cgi?id=21210
5238 static assert(!isAssignable!S5);
5240 // `-preview=in` is enabled
5241 static if (!is(typeof(mixin(q{(in ref int a) => a}))))
5243 struct S6 { void opAssign(in S5); }
5245 static assert(isRvalueAssignable!(S6, S5));
5246 static assert(isLvalueAssignable!(S6, S5));
5247 static assert(isAssignable!(S6, S5));
5248 static assert(isAssignable!(S6, immutable S5));
5250 else
5252 mixin(q{ struct S6 { void opAssign(in ref S5); } });
5254 static assert(!isRvalueAssignable!(S6, S5));
5255 static assert( isLvalueAssignable!(S6, S5));
5256 static assert(!isAssignable!(S6, S5));
5257 static assert( isLvalueAssignable!(S6, immutable S5));
5262 // Equivalent with TypeStruct::isAssignable in compiler code.
5263 package template isBlitAssignable(T)
5265 static if (is(T == enum))
5267 enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5269 else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5270 // Workaround for issue 11499 : isStaticArray!T should not be necessary.
5272 enum isBlitAssignable = isBlitAssignable!E;
5274 else static if (is(T == struct) || is(T == union))
5276 enum isBlitAssignable = isMutable!T &&
5278 size_t offset = 0;
5279 bool assignable = true;
5280 foreach (i, F; FieldTypeTuple!T)
5282 static if (i == 0)
5285 else
5287 if (T.tupleof[i].offsetof == offset)
5289 if (assignable)
5290 continue;
5292 else
5294 if (!assignable)
5295 return false;
5298 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5299 offset = T.tupleof[i].offsetof;
5301 return assignable;
5302 }();
5304 else
5305 enum isBlitAssignable = isMutable!T;
5308 @safe unittest
5310 static assert( isBlitAssignable!int);
5311 static assert(!isBlitAssignable!(const int));
5313 class C{ const int i; }
5314 static assert( isBlitAssignable!C);
5316 struct S1{ int i; }
5317 struct S2{ const int i; }
5318 static assert( isBlitAssignable!S1);
5319 static assert(!isBlitAssignable!S2);
5321 struct S3X { union { int x; int y; } }
5322 struct S3Y { union { int x; const int y; } }
5323 struct S3Z { union { const int x; const int y; } }
5324 static assert( isBlitAssignable!(S3X));
5325 static assert( isBlitAssignable!(S3Y));
5326 static assert(!isBlitAssignable!(S3Z));
5327 static assert(!isBlitAssignable!(const S3X));
5328 static assert(!isBlitAssignable!(inout S3Y));
5329 static assert(!isBlitAssignable!(immutable S3Z));
5330 static assert( isBlitAssignable!(S3X[3]));
5331 static assert( isBlitAssignable!(S3Y[3]));
5332 static assert(!isBlitAssignable!(S3Z[3]));
5333 enum ES3X : S3X { a = S3X() }
5334 enum ES3Y : S3Y { a = S3Y() }
5335 enum ES3Z : S3Z { a = S3Z() }
5336 static assert( isBlitAssignable!(ES3X));
5337 static assert( isBlitAssignable!(ES3Y));
5338 static assert(!isBlitAssignable!(ES3Z));
5339 static assert(!isBlitAssignable!(const ES3X));
5340 static assert(!isBlitAssignable!(inout ES3Y));
5341 static assert(!isBlitAssignable!(immutable ES3Z));
5342 static assert( isBlitAssignable!(ES3X[3]));
5343 static assert( isBlitAssignable!(ES3Y[3]));
5344 static assert(!isBlitAssignable!(ES3Z[3]));
5346 union U1X { int x; int y; }
5347 union U1Y { int x; const int y; }
5348 union U1Z { const int x; const int y; }
5349 static assert( isBlitAssignable!(U1X));
5350 static assert( isBlitAssignable!(U1Y));
5351 static assert(!isBlitAssignable!(U1Z));
5352 static assert(!isBlitAssignable!(const U1X));
5353 static assert(!isBlitAssignable!(inout U1Y));
5354 static assert(!isBlitAssignable!(immutable U1Z));
5355 static assert( isBlitAssignable!(U1X[3]));
5356 static assert( isBlitAssignable!(U1Y[3]));
5357 static assert(!isBlitAssignable!(U1Z[3]));
5358 enum EU1X : U1X { a = U1X() }
5359 enum EU1Y : U1Y { a = U1Y() }
5360 enum EU1Z : U1Z { a = U1Z() }
5361 static assert( isBlitAssignable!(EU1X));
5362 static assert( isBlitAssignable!(EU1Y));
5363 static assert(!isBlitAssignable!(EU1Z));
5364 static assert(!isBlitAssignable!(const EU1X));
5365 static assert(!isBlitAssignable!(inout EU1Y));
5366 static assert(!isBlitAssignable!(immutable EU1Z));
5367 static assert( isBlitAssignable!(EU1X[3]));
5368 static assert( isBlitAssignable!(EU1Y[3]));
5369 static assert(!isBlitAssignable!(EU1Z[3]));
5371 struct SA
5373 @property int[3] foo() { return [1,2,3]; }
5374 alias foo this;
5375 const int x; // SA is not blit assignable
5377 static assert(!isStaticArray!SA);
5378 static assert(!isBlitAssignable!(SA[3]));
5383 Works like `isImplicitlyConvertible`, except this cares only about storage
5384 classes of the arguments.
5386 private template isStorageClassImplicitlyConvertible(From, To)
5388 alias Pointify(T) = void*;
5390 enum isStorageClassImplicitlyConvertible = isImplicitlyConvertible!(
5391 ModifyTypePreservingTQ!(Pointify, From),
5392 ModifyTypePreservingTQ!(Pointify, To) );
5395 @safe unittest
5397 static assert( isStorageClassImplicitlyConvertible!( int, const int));
5398 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5400 static assert(!isStorageClassImplicitlyConvertible!(const int, int));
5401 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5402 static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5403 static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5408 Determines whether the function type `F` is covariant with `G`, i.e.,
5409 functions of the type `F` can override ones of the type `G`.
5411 template isCovariantWith(F, G)
5412 if (is(F == function) && is(G == function) ||
5413 is(F == delegate) && is(G == delegate) ||
5414 isFunctionPointer!F && isFunctionPointer!G)
5416 static if (is(F : G))
5417 enum isCovariantWith = true;
5418 else
5420 alias Upr = F;
5421 alias Lwr = G;
5424 * Check for calling convention: require exact match.
5426 template checkLinkage()
5428 enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5431 * Check for variadic parameter: require exact match.
5433 template checkVariadicity()
5435 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5438 * Check for function storage class:
5439 * - overrider can have narrower storage class than base
5441 template checkSTC()
5443 // Note the order of arguments. The convertion order Lwr -> Upr is
5444 // correct since Upr should be semantically 'narrower' than Lwr.
5445 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5448 * Check for function attributes:
5449 * - require exact match for ref and @property
5450 * - overrider can add pure and nothrow, but can't remove them
5451 * - @safe and @trusted are covariant with each other, unremovable
5453 template checkAttributes()
5455 alias FA = FunctionAttribute;
5456 enum uprAtts = functionAttributes!Upr;
5457 enum lwrAtts = functionAttributes!Lwr;
5459 enum wantExact = FA.ref_ | FA.property;
5460 enum safety = FA.safe | FA.trusted;
5461 enum ok =
5462 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) &&
5463 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) &&
5464 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5465 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ;
5468 * Check for return type: usual implicit convertion.
5470 template checkReturnType()
5472 enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5475 * Check for parameters:
5476 * - require exact match for types
5477 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5478 * - require exact match for in, out, ref and lazy
5479 * - overrider can add scope, but can't remove
5481 template checkParameters()
5483 alias STC = ParameterStorageClass;
5484 alias UprParams = Parameters!Upr;
5485 alias LwrParams = Parameters!Lwr;
5486 alias UprPSTCs = ParameterStorageClassTuple!Upr;
5487 alias LwrPSTCs = ParameterStorageClassTuple!Lwr;
5489 template checkNext(size_t i)
5491 static if (i < UprParams.length)
5493 enum uprStc = UprPSTCs[i];
5494 enum lwrStc = LwrPSTCs[i];
5496 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5497 enum ok =
5498 ((uprStc & wantExact ) == (lwrStc & wantExact )) &&
5499 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) &&
5500 checkNext!(i + 1).ok;
5502 else
5503 enum ok = true; // done
5505 static if (UprParams.length == LwrParams.length)
5506 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5507 else
5508 enum ok = false;
5511 /* run all the checks */
5512 enum isCovariantWith =
5513 checkLinkage !().ok &&
5514 checkVariadicity!().ok &&
5515 checkSTC !().ok &&
5516 checkAttributes !().ok &&
5517 checkReturnType !().ok &&
5518 checkParameters !().ok ;
5523 @safe unittest
5525 interface I { I clone(); }
5526 interface J { J clone(); }
5527 class C : I
5529 override C clone() // covariant overriding of I.clone()
5531 return new C;
5535 // C.clone() can override I.clone(), indeed.
5536 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5538 // C.clone() can't override J.clone(); the return type C is not implicitly
5539 // convertible to J.
5540 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5543 @safe unittest
5545 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5547 // covariant return type
5548 interface I {}
5549 interface J : I {}
5550 interface BaseA { const(I) test(int); }
5551 interface DerivA_1 : BaseA { override const(J) test(int); }
5552 interface DerivA_2 : BaseA { override J test(int); }
5553 static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5554 static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5555 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5556 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5557 static assert( isCovariantWith!(BaseA.test, BaseA.test));
5558 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5559 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5561 // function, function pointer and delegate
5562 J function() derived_function;
5563 I function() base_function;
5564 J delegate() derived_delegate;
5565 I delegate() base_delegate;
5566 static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5567 static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5568 static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5570 // scope parameter
5571 interface BaseB { void test( int*, int*); }
5572 interface DerivB_1 : BaseB { override void test(scope int*, int*); }
5573 interface DerivB_2 : BaseB { override void test( int*, scope int*); }
5574 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5575 static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5576 static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5577 static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5578 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5579 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5580 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5582 // function storage class
5583 interface BaseC { void test() ; }
5584 interface DerivC_1 : BaseC { override void test() const; }
5585 static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5586 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5588 // increasing safety
5589 interface BaseE { void test() ; }
5590 interface DerivE_1 : BaseE { override void test() @safe ; }
5591 interface DerivE_2 : BaseE { override void test() @trusted; }
5592 static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5593 static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5594 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5595 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5597 // @safe and @trusted
5598 interface BaseF
5600 void test1() @safe;
5601 void test2() @trusted;
5603 interface DerivF : BaseF
5605 override void test1() @trusted;
5606 override void test2() @safe;
5608 static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5609 static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5613 // Needed for rvalueOf/lvalueOf because "inout on return means
5614 // inout must be on a parameter as well"
5615 private struct __InoutWorkaroundStruct{}
5618 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5619 `__traits(compiles, ...)` purposes. No actual value is returned.
5621 Params:
5622 T = The type to transform
5624 Note: Trying to use returned value will result in a
5625 "Symbol Undefined" error at link time.
5627 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5629 /// ditto
5630 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5632 // Note: can't put these unittests together as function overloads
5633 // aren't allowed inside functions.
5635 @system unittest
5637 static int f(int);
5638 static assert(is(typeof(f(rvalueOf!int)) == int));
5642 @system unittest
5644 static bool f(ref int);
5645 static assert(is(typeof(f(lvalueOf!int)) == bool));
5648 @system unittest
5650 void needLvalue(T)(ref T);
5651 static struct S { }
5652 int i;
5653 struct Nested { void f() { ++i; } }
5654 static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5656 static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5657 static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5658 static assert(is(typeof(rvalueOf!T) == T));
5659 static assert(is(typeof(lvalueOf!T) == T));
5662 static assert(!__traits(compiles, rvalueOf!int = 1));
5663 static assert( __traits(compiles, lvalueOf!byte = 127));
5664 static assert(!__traits(compiles, lvalueOf!byte = 128));
5668 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5669 // SomethingTypeOf
5670 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5674 template BooleanTypeOf(T)
5676 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5677 alias X = BooleanTypeOf!AT;
5678 else
5679 alias X = OriginalType!T;
5681 static if (is(immutable X == immutable bool))
5683 alias BooleanTypeOf = X;
5685 else
5686 static assert(0, T.stringof~" is not boolean type");
5689 @safe unittest
5691 // unexpected failure, maybe dmd type-merging bug
5692 static foreach (T; AliasSeq!bool)
5693 static foreach (Q; TypeQualifierList)
5695 static assert( is(Q!T == BooleanTypeOf!( Q!T )));
5696 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5699 static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5700 static foreach (Q; TypeQualifierList)
5702 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof);
5703 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5707 @safe unittest
5709 struct B
5711 bool val;
5712 alias val this;
5714 struct S
5716 B b;
5717 alias b this;
5719 static assert(is(BooleanTypeOf!B == bool));
5720 static assert(is(BooleanTypeOf!S == bool));
5725 template IntegralTypeOf(T)
5727 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5728 alias X = IntegralTypeOf!AT;
5729 else
5730 alias X = OriginalType!T;
5732 static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5733 && !is(immutable X == immutable bool) && !is(X == __vector))
5735 alias IntegralTypeOf = X;
5737 else
5738 static assert(0, T.stringof~" is not an integral type");
5741 @safe unittest
5743 static foreach (T; IntegralTypeList)
5744 static foreach (Q; TypeQualifierList)
5746 static assert( is(Q!T == IntegralTypeOf!( Q!T )));
5747 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5750 static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5751 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5752 static foreach (Q; TypeQualifierList)
5754 static assert(!is(IntegralTypeOf!( Q!T )));
5755 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5761 template FloatingPointTypeOf(T)
5763 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5764 alias X = FloatingPointTypeOf!AT;
5765 else
5766 alias X = OriginalType!T;
5768 static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5770 alias FloatingPointTypeOf = X;
5772 else
5773 static assert(0, T.stringof~" is not a floating point type");
5776 @safe unittest
5778 static foreach (T; FloatingPointTypeList)
5779 static foreach (Q; TypeQualifierList)
5781 static assert( is(Q!T == FloatingPointTypeOf!( Q!T )));
5782 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5785 static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5786 static foreach (Q; TypeQualifierList)
5788 static assert(!is(FloatingPointTypeOf!( Q!T )));
5789 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5795 template NumericTypeOf(T)
5797 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5799 alias NumericTypeOf = X;
5801 else
5802 static assert(0, T.stringof~" is not a numeric type");
5805 @safe unittest
5807 static foreach (T; NumericTypeList)
5808 static foreach (Q; TypeQualifierList)
5810 static assert( is(Q!T == NumericTypeOf!( Q!T )));
5811 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5814 static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5815 static foreach (Q; TypeQualifierList)
5817 static assert(!is(NumericTypeOf!( Q!T )));
5818 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5824 template UnsignedTypeOf(T)
5826 static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5827 alias UnsignedTypeOf = X;
5828 else
5829 static assert(0, T.stringof~" is not an unsigned type.");
5834 template SignedTypeOf(T)
5836 static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5837 alias SignedTypeOf = X;
5838 else static if (is(FloatingPointTypeOf!T X))
5839 alias SignedTypeOf = X;
5840 else
5841 static assert(0, T.stringof~" is not an signed type.");
5846 template CharTypeOf(T)
5848 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5849 alias X = CharTypeOf!AT;
5850 else
5851 alias X = OriginalType!T;
5853 static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5855 alias CharTypeOf = X;
5857 else
5858 static assert(0, T.stringof~" is not a character type");
5861 @safe unittest
5863 static foreach (T; CharTypeList)
5864 static foreach (Q; TypeQualifierList)
5866 static assert( is(CharTypeOf!( Q!T )));
5867 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5870 static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5871 static foreach (Q; TypeQualifierList)
5873 static assert(!is(CharTypeOf!( Q!T )));
5874 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5877 static foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5878 static foreach (Q; TypeQualifierList)
5880 static assert(!is(CharTypeOf!( Q!T )));
5881 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5887 template StaticArrayTypeOf(T)
5889 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5890 alias X = StaticArrayTypeOf!AT;
5891 else
5892 alias X = OriginalType!T;
5894 static if (__traits(isStaticArray, X))
5895 alias StaticArrayTypeOf = X;
5896 else
5897 static assert(0, T.stringof~" is not a static array type");
5900 @safe unittest
5902 static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5903 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5905 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) ));
5907 static foreach (P; TypeQualifierList)
5908 { // SubTypeOf cannot have inout type
5909 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
5913 static foreach (T; AliasSeq!void)
5914 static foreach (Q; AliasSeq!TypeQualifierList)
5916 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
5922 template DynamicArrayTypeOf(T)
5924 import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
5925 alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
5928 @safe unittest
5930 import std.meta : Alias;
5931 static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5932 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
5934 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) ));
5935 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) ));
5937 static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
5939 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
5940 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
5944 static assert(!is(DynamicArrayTypeOf!(int[3])));
5945 static assert(!is(DynamicArrayTypeOf!(void[3])));
5946 static assert(!is(DynamicArrayTypeOf!(typeof(null))));
5951 template ArrayTypeOf(T)
5953 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
5955 alias ArrayTypeOf = X;
5957 else
5958 static assert(0, T.stringof~" is not an array type");
5962 * Converts strings and string-like types to the corresponding dynamic array of characters.
5963 * Params:
5964 * T = one of the following:
5965 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
5966 * (`shared` is rejected)
5967 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
5968 * (`shared` is rejected)
5969 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
5971 * Other cases are rejected with a compile time error.
5972 * `typeof(null)` is rejected.
5974 * Returns:
5975 * The result of `[]` applied to the qualified character type.
5977 template StringTypeOf(T)
5979 static if (is(T == typeof(null)))
5981 // It is impossible to determine exact string type from typeof(null) -
5982 // it means that StringTypeOf!(typeof(null)) is undefined.
5983 // Then this behavior is convenient for template constraint.
5984 static assert(0, T.stringof~" is not a string type");
5986 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
5988 static if (is(T : U[], U))
5989 alias StringTypeOf = U[];
5990 else
5991 static assert(0);
5993 else
5994 static assert(0, T.stringof~" is not a string type");
5997 @safe unittest
5999 import std.meta : Alias;
6000 static foreach (T; CharTypeList)
6001 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6003 static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6005 static if (!__traits(isSame, Q, InoutOf))
6007 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6009 alias Str = Q!T[];
6010 class C(S) { S val; alias val this; }
6011 static assert(is(StringTypeOf!(C!Str) == Str));
6015 static foreach (T; CharTypeList)
6016 static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6018 static assert(!is(StringTypeOf!( Q!T[] )));
6022 @safe unittest
6024 static assert(is(StringTypeOf!(char[4]) == char[]));
6026 struct S
6028 string s;
6029 alias s this;
6032 struct T
6034 S s;
6035 alias s this;
6038 static assert(is(StringTypeOf!S == string));
6039 static assert(is(StringTypeOf!T == string));
6044 template AssocArrayTypeOf(T)
6046 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6047 alias X = AssocArrayTypeOf!AT;
6048 else
6049 alias X = OriginalType!T;
6051 static if (__traits(isAssociativeArray, X))
6053 alias AssocArrayTypeOf = X;
6055 else
6056 static assert(0, T.stringof~" is not an associative array type");
6059 @safe unittest
6061 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6062 static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6063 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6064 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6066 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) ));
6069 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6070 static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6071 static foreach (P; AliasSeq!TypeQualifierList)
6072 static foreach (Q; AliasSeq!TypeQualifierList)
6073 static foreach (R; AliasSeq!TypeQualifierList)
6075 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6081 template BuiltinTypeOf(T)
6083 static if (is(T : void))
6084 alias BuiltinTypeOf = void;
6085 else
6087 static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6088 alias X = BuiltinTypeOf!AT;
6089 else
6090 alias X = OriginalType!T;
6091 static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6092 __traits(isStaticArray, X) || is(X == E[], E) ||
6093 __traits(isAssociativeArray, X))
6094 alias BuiltinTypeOf = X;
6095 else
6096 static assert(0);
6100 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6101 // isSomething
6102 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6105 * Detect whether `T` is a built-in boolean type.
6107 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6110 @safe unittest
6112 static assert( isBoolean!bool);
6113 enum EB : bool { a = true }
6114 static assert( isBoolean!EB);
6115 static assert(!isBoolean!(SubTypeOf!bool));
6118 @safe unittest
6120 static struct S(T)
6122 T t;
6123 alias t this;
6125 static assert(!isIntegral!(S!bool));
6129 * Detect whether `T` is a built-in integral type. Types `bool`,
6130 * `char`, `wchar`, and `dchar` are not considered integral.
6132 template isIntegral(T)
6134 static if (!__traits(isIntegral, T))
6135 enum isIntegral = false;
6136 else static if (is(T U == enum))
6137 enum isIntegral = isIntegral!U;
6138 else
6139 enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6140 && !is(immutable T == immutable bool) && !is(T == __vector);
6144 @safe unittest
6146 static assert(
6147 isIntegral!byte &&
6148 isIntegral!short &&
6149 isIntegral!int &&
6150 isIntegral!long &&
6151 isIntegral!(const(long)) &&
6152 isIntegral!(immutable(long))
6155 static assert(
6156 !isIntegral!bool &&
6157 !isIntegral!char &&
6158 !isIntegral!double
6161 // types which act as integral values do not pass
6162 struct S
6164 int val;
6165 alias val this;
6168 static assert(!isIntegral!S);
6171 @safe unittest
6173 static foreach (T; IntegralTypeList)
6175 static foreach (Q; TypeQualifierList)
6177 static assert( isIntegral!(Q!T));
6178 static assert(!isIntegral!(SubTypeOf!(Q!T)));
6182 static assert(!isIntegral!float);
6184 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
6185 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6186 enum EI : int { a = -1, b = 0, c = 1 }
6187 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU);
6188 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI);
6192 * Detect whether `T` is a built-in floating point type.
6194 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6197 @safe unittest
6199 static assert(
6200 isFloatingPoint!float &&
6201 isFloatingPoint!double &&
6202 isFloatingPoint!real &&
6203 isFloatingPoint!(const(real)) &&
6204 isFloatingPoint!(immutable(real))
6207 static assert(!isFloatingPoint!int);
6209 // types which act as floating point values do not pass
6210 struct S
6212 float val;
6213 alias val this;
6216 static assert(!isFloatingPoint!S);
6219 @safe unittest
6221 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6223 static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6225 static foreach (Q; TypeQualifierList)
6227 static assert( isFloatingPoint!(Q!T));
6228 static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6231 static foreach (T; IntegralTypeList)
6233 static foreach (Q; TypeQualifierList)
6235 static assert(!isFloatingPoint!(Q!T));
6238 static if (is(__vector(float[4])))
6240 static assert(!isFloatingPoint!(__vector(float[4])));
6245 * Detect whether `T` is a built-in numeric type (integral or floating
6246 * point).
6248 template isNumeric(T)
6250 static if (!__traits(isArithmetic, T))
6251 enum isNumeric = false;
6252 else static if (__traits(isFloating, T))
6253 enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6254 else static if (is(T U == enum))
6255 enum isNumeric = isNumeric!U;
6256 else
6257 enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6258 && !is(immutable T == immutable bool) && !is(T == __vector);
6262 @safe unittest
6264 static assert(
6265 isNumeric!byte &&
6266 isNumeric!short &&
6267 isNumeric!int &&
6268 isNumeric!long &&
6269 isNumeric!float &&
6270 isNumeric!double &&
6271 isNumeric!real &&
6272 isNumeric!(const(real)) &&
6273 isNumeric!(immutable(real))
6276 static assert(
6277 !isNumeric!void &&
6278 !isNumeric!bool &&
6279 !isNumeric!char &&
6280 !isNumeric!wchar &&
6281 !isNumeric!dchar
6284 // types which act as numeric values do not pass
6285 struct S
6287 int val;
6288 alias val this;
6291 static assert(!isNumeric!S);
6294 @safe unittest
6296 static foreach (T; AliasSeq!(NumericTypeList))
6298 static foreach (Q; TypeQualifierList)
6300 static assert( isNumeric!(Q!T));
6301 static assert(!isNumeric!(SubTypeOf!(Q!T)));
6305 static struct S(T)
6307 T t;
6308 alias t this;
6310 static assert(!isNumeric!(S!int));
6312 enum EChar : char { a = 0, }
6313 static assert(!isNumeric!EChar);
6315 static if (is(__vector(float[4])))
6317 static assert(!isNumeric!(__vector(float[4])));
6319 static if (is(__vector(int[4])))
6321 static assert(!isNumeric!(__vector(int[4])));
6324 static assert(!isNumeric!ifloat);
6325 static assert(!isNumeric!cfloat);
6329 * Detect whether `T` is a scalar type (a built-in numeric, character or
6330 * boolean type).
6332 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6335 @safe unittest
6337 static assert(!isScalarType!void);
6338 static assert( isScalarType!(immutable(byte)));
6339 static assert( isScalarType!(immutable(ushort)));
6340 static assert( isScalarType!(immutable(int)));
6341 static assert( isScalarType!(ulong));
6342 static assert( isScalarType!(shared(float)));
6343 static assert( isScalarType!(shared(const bool)));
6344 static assert( isScalarType!(const(char)));
6345 static assert( isScalarType!(wchar));
6346 static assert( isScalarType!(const(dchar)));
6347 static assert( isScalarType!(const(double)));
6348 static assert( isScalarType!(const(real)));
6351 @safe unittest
6353 static struct S(T)
6355 T t;
6356 alias t this;
6358 static assert(!isScalarType!(S!int));
6362 * Detect whether `T` is a basic type (scalar type or void).
6364 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6367 @safe unittest
6369 static assert(isBasicType!void);
6370 static assert(isBasicType!(const(void)));
6371 static assert(isBasicType!(shared(void)));
6372 static assert(isBasicType!(immutable(void)));
6373 static assert(isBasicType!(shared const(void)));
6374 static assert(isBasicType!(shared inout(void)));
6375 static assert(isBasicType!(shared inout const(void)));
6376 static assert(isBasicType!(inout(void)));
6377 static assert(isBasicType!(inout const(void)));
6378 static assert(isBasicType!(immutable(int)));
6379 static assert(isBasicType!(shared(float)));
6380 static assert(isBasicType!(shared(const bool)));
6381 static assert(isBasicType!(const(dchar)));
6385 * Detect whether `T` is a built-in unsigned numeric type.
6387 template isUnsigned(T)
6389 static if (!__traits(isUnsigned, T))
6390 enum isUnsigned = false;
6391 else static if (is(T U == enum))
6392 enum isUnsigned = isUnsigned!U;
6393 else
6394 enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6395 && !is(immutable T == immutable bool) && !is(T == __vector);
6399 @safe unittest
6401 static assert(
6402 isUnsigned!uint &&
6403 isUnsigned!ulong
6406 static assert(
6407 !isUnsigned!char &&
6408 !isUnsigned!int &&
6409 !isUnsigned!long &&
6410 !isUnsigned!char &&
6411 !isUnsigned!wchar &&
6412 !isUnsigned!dchar
6416 @safe unittest
6418 static foreach (T; AliasSeq!(UnsignedIntTypeList))
6420 static foreach (Q; TypeQualifierList)
6422 static assert( isUnsigned!(Q!T));
6423 static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6427 static struct S(T)
6429 T t;
6430 alias t this;
6432 static assert(!isUnsigned!(S!uint));
6434 enum EChar : char { a = 0, }
6435 static assert(!isUnsigned!EChar);
6437 static if (is(__vector(uint[4])))
6439 static assert(!isUnsigned!(__vector(uint[4])));
6444 * Detect whether `T` is a built-in signed numeric type.
6446 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6447 && is(T : real);
6450 @safe unittest
6452 static assert(
6453 isSigned!int &&
6454 isSigned!long
6457 static assert(
6458 !isSigned!uint &&
6459 !isSigned!ulong
6463 @safe unittest
6465 enum E { e1 = 0 }
6466 static assert(isSigned!E);
6468 enum Eubyte : ubyte { e1 = 0 }
6469 static assert(!isSigned!Eubyte);
6471 static foreach (T; AliasSeq!(SignedIntTypeList))
6473 static foreach (Q; TypeQualifierList)
6475 static assert( isSigned!(Q!T));
6476 static assert(!isSigned!(SubTypeOf!(Q!T)));
6480 static struct S(T)
6482 T t;
6483 alias t this;
6485 static assert(!isSigned!(S!uint));
6487 static if (is(__vector(int[4])))
6489 static assert(!isSigned!(__vector(int[4])));
6492 static assert(!isSigned!ifloat);
6493 static assert(!isSigned!cfloat);
6496 // https://issues.dlang.org/show_bug.cgi?id=17196
6497 @safe unittest
6499 static assert(isUnsigned!bool == false);
6500 static assert(isSigned!bool == false);
6504 * Detect whether `T` is one of the built-in character types.
6506 * The built-in char types are any of `char`, `wchar` or `dchar`, with
6507 * or without qualifiers.
6509 template isSomeChar(T)
6511 static if (!__traits(isUnsigned, T))
6512 enum isSomeChar = false;
6513 else static if (is(T U == enum))
6514 enum isSomeChar = isSomeChar!U;
6515 else
6516 enum isSomeChar = !__traits(isZeroInit, T);
6520 @safe unittest
6522 //Char types
6523 static assert( isSomeChar!char);
6524 static assert( isSomeChar!wchar);
6525 static assert( isSomeChar!dchar);
6526 static assert( isSomeChar!(typeof('c')));
6527 static assert( isSomeChar!(immutable char));
6528 static assert( isSomeChar!(const dchar));
6530 //Non char types
6531 static assert(!isSomeChar!int);
6532 static assert(!isSomeChar!byte);
6533 static assert(!isSomeChar!string);
6534 static assert(!isSomeChar!wstring);
6535 static assert(!isSomeChar!dstring);
6536 static assert(!isSomeChar!(char[4]));
6539 @safe unittest
6541 enum EC : char { a = 'x', b = 'y' }
6543 static foreach (T; AliasSeq!(CharTypeList, EC))
6545 static foreach (Q; TypeQualifierList)
6547 static assert( isSomeChar!( Q!T ));
6548 static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6552 // alias-this types are not allowed
6553 static struct S(T)
6555 T t;
6556 alias t this;
6558 static assert(!isSomeChar!(S!char));
6562 Detect whether `T` is one of the built-in string types.
6564 The built-in string types are `Char[]`, where `Char` is any of `char`,
6565 `wchar` or `dchar`, with or without qualifiers.
6567 Static arrays of characters (like `char[80]`) are not considered
6568 built-in string types.
6570 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6573 @safe unittest
6575 //String types
6576 static assert( isSomeString!string);
6577 static assert( isSomeString!(wchar[]));
6578 static assert( isSomeString!(dchar[]));
6579 static assert( isSomeString!(typeof("aaa")));
6580 static assert( isSomeString!(const(char)[]));
6582 //Non string types
6583 static assert(!isSomeString!int);
6584 static assert(!isSomeString!(int[]));
6585 static assert(!isSomeString!(byte[]));
6586 static assert(!isSomeString!(typeof(null)));
6587 static assert(!isSomeString!(char[4]));
6589 enum ES : string { a = "aaa", b = "bbb" }
6590 static assert(!isSomeString!ES);
6592 static struct Stringish
6594 string str;
6595 alias str this;
6597 static assert(!isSomeString!Stringish);
6600 @safe unittest
6602 static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6604 static assert( isSomeString!( T ));
6605 static assert(!isSomeString!(SubTypeOf!(T)));
6607 enum C : char { _ = 0 }
6608 static assert(!isSomeString!(C[]));
6612 * Detect whether type `T` is a narrow string.
6614 * All arrays that use char, wchar, and their qualified versions are narrow
6615 * strings. (Those include string and wstring).
6617 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6620 @safe unittest
6622 static assert(isNarrowString!string);
6623 static assert(isNarrowString!wstring);
6624 static assert(isNarrowString!(char[]));
6625 static assert(isNarrowString!(wchar[]));
6627 static assert(!isNarrowString!dstring);
6628 static assert(!isNarrowString!(dchar[]));
6630 static assert(!isNarrowString!(typeof(null)));
6631 static assert(!isNarrowString!(char[4]));
6633 enum ES : string { a = "aaa", b = "bbb" }
6634 static assert(!isNarrowString!ES);
6636 static struct Stringish
6638 string str;
6639 alias str this;
6641 static assert(!isNarrowString!Stringish);
6644 @safe unittest
6646 import std.meta : Alias;
6647 static foreach (T; AliasSeq!(char[], string, wstring))
6649 static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6651 static assert( isNarrowString!( Q!T ));
6652 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6656 static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6658 static foreach (Q; TypeQualifierList)
6660 static assert(!isNarrowString!( Q!T ));
6661 static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6664 enum C : char { _ = 0 }
6665 static assert(!isNarrowString!(C[]));
6669 * Detects whether `T` is a comparable type. Basic types and structs and
6670 * classes that implement opCmp are ordering comparable.
6672 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6675 @safe unittest
6677 static assert(isOrderingComparable!int);
6678 static assert(isOrderingComparable!string);
6680 static struct Foo {}
6681 static assert(!isOrderingComparable!Foo);
6683 static struct Bar
6685 int a;
6686 auto opCmp(Bar b1) const { return a - b1.a; }
6689 Bar b1 = Bar(5);
6690 Bar b2 = Bar(7);
6691 assert(isOrderingComparable!Bar && b2 > b1);
6694 /// ditto
6695 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6697 @safe unittest
6699 static assert(isEqualityComparable!int);
6700 static assert(isEqualityComparable!string);
6701 static assert(!isEqualityComparable!void);
6703 struct Foo {}
6704 static assert(isEqualityComparable!Foo);
6706 struct Bar
6708 int a;
6709 auto opEquals(Bar b1) const { return a == b1.a; }
6712 Bar b1 = Bar(5);
6713 Bar b2 = Bar(5);
6714 Bar b3 = Bar(7);
6715 static assert(isEqualityComparable!Bar);
6716 assert(b1 == b2);
6717 assert(b1 != b3);
6721 $(RED Warning: This trait will be deprecated as soon as it is no longer used
6722 in Phobos. For a function parameter to safely accept a type
6723 that implicitly converts to string as a string, the conversion
6724 needs to happen at the callsite; otherwise, the conversion is
6725 done inside the function, and in many cases, that means that
6726 local memory is sliced (e.g. if a static array is passed to
6727 the function, then it's copied, and the resulting dynamic
6728 array will be a slice of a local variable). So, if the
6729 resulting string escapes the function, the string refers to
6730 invalid memory, and accessing it would mean accessing invalid
6731 memory. As such, the only safe way for a function to accept
6732 types that implicitly convert to string is for the implicit
6733 conversion to be done at the callsite, and that can only occur
6734 if the parameter is explicitly typed as an array, whereas
6735 using isConvertibleToString in a template constraint would
6736 result in the conversion being done inside the function. As
6737 such, isConvertibleToString is inherently unsafe and is going
6738 to be deprecated.)
6740 Detect whether `T` is a struct, static array, or enum that is implicitly
6741 convertible to a string.
6743 template isConvertibleToString(T)
6745 enum isConvertibleToString =
6746 (isAggregateType!T || isStaticArray!T || is(T == enum))
6747 && is(StringTypeOf!T);
6751 @safe unittest
6753 static struct AliasedString
6755 string s;
6756 alias s this;
6759 enum StringEnum { a = "foo" }
6761 assert(!isConvertibleToString!string);
6762 assert(isConvertibleToString!AliasedString);
6763 assert(isConvertibleToString!StringEnum);
6764 assert(isConvertibleToString!(char[25]));
6765 assert(!isConvertibleToString!(char[]));
6768 // https://issues.dlang.org/show_bug.cgi?id=16573
6769 @safe unittest
6771 enum I : int { foo = 1 }
6772 enum S : string { foo = "foo" }
6773 assert(!isConvertibleToString!I);
6774 assert(isConvertibleToString!S);
6777 package template convertToString(T)
6779 static if (isConvertibleToString!T)
6780 alias convertToString = StringTypeOf!T;
6781 else
6782 alias convertToString = T;
6786 * Detect whether type `T` is a string that will be autodecoded.
6788 * Given a type `S` that is one of:
6789 * $(OL
6790 * $(LI `const(char)[]`)
6791 * $(LI `const(wchar)[]`)
6793 * Type `T` can be one of:
6794 * $(OL
6795 * $(LI `S`)
6796 * $(LI implicitly convertible to `T`)
6797 * $(LI an enum with a base type `T`)
6798 * $(LI an aggregate with a base type `T`)
6800 * with the proviso that `T` cannot be a static array.
6802 * Params:
6803 * T = type to be tested
6805 * Returns:
6806 * true if T represents a string that is subject to autodecoding
6808 * See Also:
6809 * $(LREF isNarrowString)
6811 template isAutodecodableString(T)
6813 import std.range.primitives : autodecodeStrings;
6815 enum isAutodecodableString = autodecodeStrings &&
6816 (is(T : const char[]) || is(T : const wchar[]))
6817 && !is(T : U[n], U, size_t n)
6818 && !is(immutable T : immutable noreturn[]);
6822 @safe unittest
6824 static struct Stringish
6826 string s;
6827 alias s this;
6829 static assert(isAutodecodableString!wstring);
6830 static assert(isAutodecodableString!Stringish);
6831 static assert(!isAutodecodableString!dstring);
6833 enum E : const(char)[3] { X = "abc" }
6834 enum F : const(char)[] { X = "abc" }
6835 enum G : F { X = F.init }
6837 static assert(isAutodecodableString!(char[]));
6838 static assert(!isAutodecodableString!(E));
6839 static assert(isAutodecodableString!(F));
6840 static assert(isAutodecodableString!(G));
6842 struct Stringish2
6844 Stringish s;
6845 alias s this;
6848 enum H : Stringish { X = Stringish() }
6849 enum I : Stringish2 { X = Stringish2() }
6851 static assert(isAutodecodableString!(H));
6852 static assert(isAutodecodableString!(I));
6854 static assert(!isAutodecodableString!(noreturn[]));
6855 static assert(!isAutodecodableString!(immutable(noreturn)[]));
6859 * Detect whether type `T` is a static array.
6861 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6864 @safe unittest
6866 static assert( isStaticArray!(int[3]));
6867 static assert( isStaticArray!(const(int)[5]));
6868 static assert( isStaticArray!(const(int)[][5]));
6870 static assert(!isStaticArray!(const(int)[]));
6871 static assert(!isStaticArray!(immutable(int)[]));
6872 static assert(!isStaticArray!(const(int)[4][]));
6873 static assert(!isStaticArray!(int[]));
6874 static assert(!isStaticArray!(int[char]));
6875 static assert(!isStaticArray!(int[1][]));
6876 static assert(!isStaticArray!(int[int]));
6877 static assert(!isStaticArray!int);
6880 @safe unittest
6882 static foreach (T; AliasSeq!(int[51], int[][2],
6883 char[][int][11], immutable char[13u],
6884 const(real)[1], const(real)[1][1], void[0]))
6886 static foreach (Q; TypeQualifierList)
6888 static assert( isStaticArray!( Q!T ));
6889 static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
6893 //enum ESA : int[1] { a = [1], b = [2] }
6894 //static assert( isStaticArray!ESA);
6898 * Detect whether type `T` is a dynamic array.
6900 template isDynamicArray(T)
6902 static if (is(T == U[], U))
6903 enum bool isDynamicArray = true;
6904 else static if (is(T U == enum))
6905 // BUG: isDynamicArray / isStaticArray considers enums
6906 // with appropriate base types as dynamic/static arrays
6907 // Retain old behaviour for now, see
6908 // https://github.com/dlang/phobos/pull/7574
6909 enum bool isDynamicArray = isDynamicArray!U;
6910 else
6911 enum bool isDynamicArray = false;
6915 @safe unittest
6917 static assert( isDynamicArray!(int[]));
6918 static assert( isDynamicArray!(string));
6919 static assert( isDynamicArray!(long[3][]));
6921 static assert(!isDynamicArray!(int[5]));
6922 static assert(!isDynamicArray!(typeof(null)));
6925 @safe unittest
6927 import std.meta : AliasSeq;
6928 static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
6930 static foreach (Q; TypeQualifierList)
6932 static assert( isDynamicArray!( Q!T ));
6933 static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
6937 static assert(!isDynamicArray!(int[5]));
6939 static struct AliasThis
6941 int[] values;
6942 alias values this;
6945 static assert(!isDynamicArray!AliasThis);
6947 // https://github.com/dlang/phobos/pull/7574/files#r464115492
6948 enum E : string
6950 a = "a",
6951 b = "b",
6953 static assert( isDynamicArray!E);
6957 * Detect whether type `T` is an array (static or dynamic; for associative
6958 * arrays see $(LREF isAssociativeArray)).
6960 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
6963 @safe unittest
6965 static assert( isArray!(int[]));
6966 static assert( isArray!(int[5]));
6967 static assert( isArray!(string));
6969 static assert(!isArray!uint);
6970 static assert(!isArray!(uint[uint]));
6971 static assert(!isArray!(typeof(null)));
6974 @safe unittest
6976 import std.meta : AliasSeq;
6977 static foreach (T; AliasSeq!(int[], int[5], void[]))
6979 static foreach (Q; TypeQualifierList)
6981 static assert( isArray!(Q!T));
6982 static assert(!isArray!(SubTypeOf!(Q!T)));
6988 * Detect whether `T` is an associative array type
6990 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
6992 @safe unittest
6994 struct Foo
6996 @property uint[] keys() { return null; }
6997 @property uint[] values() { return null; }
7000 static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7002 static foreach (Q; TypeQualifierList)
7004 static assert( isAssociativeArray!(Q!T));
7005 static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7009 static assert(!isAssociativeArray!Foo);
7010 static assert(!isAssociativeArray!int);
7011 static assert(!isAssociativeArray!(int[]));
7012 static assert(!isAssociativeArray!(typeof(null)));
7014 //enum EAA : int[int] { a = [1:1], b = [2:2] }
7015 //static assert( isAssociativeArray!EAA);
7019 * Detect whether type `T` is a builtin type.
7021 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7024 @safe unittest
7026 class C;
7027 union U;
7028 struct S;
7029 interface I;
7031 static assert( isBuiltinType!void);
7032 static assert( isBuiltinType!string);
7033 static assert( isBuiltinType!(int[]));
7034 static assert( isBuiltinType!(C[string]));
7035 static assert(!isBuiltinType!C);
7036 static assert(!isBuiltinType!U);
7037 static assert(!isBuiltinType!S);
7038 static assert(!isBuiltinType!I);
7039 static assert(!isBuiltinType!(void delegate(int)));
7043 * Detect whether type `T` is a SIMD vector type.
7045 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7047 @safe unittest
7049 static if (is(__vector(float[4])))
7051 alias SimdVec = __vector(float[4]);
7052 static assert(isSIMDVector!(__vector(float[4])));
7053 static assert(isSIMDVector!SimdVec);
7055 static assert(!isSIMDVector!uint);
7056 static assert(!isSIMDVector!(float[4]));
7060 * Detect whether type `T` is a pointer.
7062 enum bool isPointer(T) = is(T == U*, U) && __traits(isScalar, T);
7064 @safe unittest
7066 static foreach (T; AliasSeq!(int*, void*, char[]*))
7068 static foreach (Q; TypeQualifierList)
7070 static assert( isPointer!(Q!T));
7071 static assert(!isPointer!(SubTypeOf!(Q!T)));
7075 static assert(!isPointer!uint);
7076 static assert(!isPointer!(uint[uint]));
7077 static assert(!isPointer!(char[]));
7078 static assert(!isPointer!(typeof(null)));
7082 Returns the target type of a pointer.
7084 alias PointerTarget(T : T*) = T;
7087 @safe unittest
7089 static assert(is(PointerTarget!(int*) == int));
7090 static assert(is(PointerTarget!(void*) == void));
7094 * Detect whether type `T` is an aggregate type.
7096 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
7097 is(T == class) || is(T == interface);
7100 @safe unittest
7102 class C;
7103 union U;
7104 struct S;
7105 interface I;
7107 static assert( isAggregateType!C);
7108 static assert( isAggregateType!U);
7109 static assert( isAggregateType!S);
7110 static assert( isAggregateType!I);
7111 static assert(!isAggregateType!void);
7112 static assert(!isAggregateType!string);
7113 static assert(!isAggregateType!(int[]));
7114 static assert(!isAggregateType!(C[string]));
7115 static assert(!isAggregateType!(void delegate(int)));
7119 * Returns `true` if T can be iterated over using a `foreach` loop with
7120 * a single loop variable of automatically inferred type, regardless of how
7121 * the `foreach` loop is implemented. This includes ranges, structs/classes
7122 * that define `opApply` with a single loop variable, and builtin dynamic,
7123 * static and associative arrays.
7125 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7128 @safe unittest
7130 struct OpApply
7132 int opApply(scope int delegate(ref uint) dg) { assert(0); }
7135 struct Range
7137 @property uint front() { assert(0); }
7138 void popFront() { assert(0); }
7139 enum bool empty = false;
7142 static assert( isIterable!(uint[]));
7143 static assert( isIterable!OpApply);
7144 static assert( isIterable!(uint[string]));
7145 static assert( isIterable!Range);
7147 static assert(!isIterable!uint);
7151 * Returns true if T is not const or immutable. Note that isMutable is true for
7152 * string, or immutable(char)[], because the 'head' is mutable.
7154 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7157 @safe unittest
7159 static assert( isMutable!int);
7160 static assert( isMutable!string);
7161 static assert( isMutable!(shared int));
7162 static assert( isMutable!(shared const(int)[]));
7164 static assert(!isMutable!(const int));
7165 static assert(!isMutable!(inout int));
7166 static assert(!isMutable!(shared(const int)));
7167 static assert(!isMutable!(shared(inout int)));
7168 static assert(!isMutable!(immutable string));
7172 * Returns true if T is an instance of the template S.
7174 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7175 /// ditto
7176 template isInstanceOf(alias S, alias T)
7178 enum impl(alias T : S!Args, Args...) = true;
7179 enum impl(alias T) = false;
7180 enum isInstanceOf = impl!T;
7184 @safe unittest
7186 static struct Foo(T...) { }
7187 static struct Bar(T...) { }
7188 static struct Doo(T) { }
7189 static struct ABC(int x) { }
7190 static void fun(T)() { }
7191 template templ(T) { }
7193 static assert(isInstanceOf!(Foo, Foo!int));
7194 static assert(!isInstanceOf!(Foo, Bar!int));
7195 static assert(!isInstanceOf!(Foo, int));
7196 static assert(isInstanceOf!(Doo, Doo!int));
7197 static assert(isInstanceOf!(ABC, ABC!1));
7198 static assert(!isInstanceOf!(Foo, Foo));
7199 static assert(isInstanceOf!(fun, fun!int));
7200 static assert(isInstanceOf!(templ, templ!int));
7204 * To use `isInstanceOf` to check the identity of a template while inside of said
7205 * template, use $(LREF TemplateOf).
7207 @safe unittest
7209 static struct A(T = void)
7211 // doesn't work as expected, only accepts A when T = void
7212 void func(B)(B b) if (isInstanceOf!(A, B)) {}
7214 // correct behavior
7215 void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {}
7218 A!(void) a1;
7219 A!(void) a2;
7220 A!(int) a3;
7222 static assert(!__traits(compiles, a1.func(a3)));
7223 static assert( __traits(compiles, a1.method(a2)));
7224 static assert( __traits(compiles, a1.method(a3)));
7227 @safe unittest
7229 static void fun1(T)() { }
7230 static void fun2(T)() { }
7231 template templ1(T) { }
7232 template templ2(T) { }
7234 static assert(!isInstanceOf!(fun1, fun2!int));
7235 static assert(!isInstanceOf!(templ1, templ2!int));
7239 * Check whether the tuple T is an expression tuple.
7240 * An expression tuple only contains expressions.
7242 * See_Also: $(LREF isTypeTuple).
7244 template isExpressions(T...)
7246 static foreach (Ti; T)
7248 static if (!is(typeof(isExpressions) == bool) && // not yet defined
7249 (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7251 enum isExpressions = false;
7254 static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7256 enum isExpressions = true;
7261 @safe unittest
7263 static assert(isExpressions!(1, 2.0, "a"));
7264 static assert(!isExpressions!(int, double, string));
7265 static assert(!isExpressions!(int, 2.0, "a"));
7269 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7272 alias isExpressionTuple = isExpressions;
7274 @safe unittest
7276 void foo();
7277 static int bar() { return 42; }
7278 immutable aa = [ 1: -1 ];
7279 alias myint = int;
7281 static assert( isExpressionTuple!(42));
7282 static assert( isExpressionTuple!aa);
7283 static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7284 static assert( isExpressionTuple!(bar()));
7286 static assert(!isExpressionTuple!isExpressionTuple);
7287 static assert(!isExpressionTuple!foo);
7288 static assert(!isExpressionTuple!( (a) { } ));
7289 static assert(!isExpressionTuple!int);
7290 static assert(!isExpressionTuple!myint);
7295 * Check whether the tuple `T` is a type tuple.
7296 * A type tuple only contains types.
7298 * See_Also: $(LREF isExpressions).
7300 enum isTypeTuple(T...) =
7302 static foreach (U; T)
7303 static if (!is(U))
7304 if (__ctfe)
7305 return false;
7306 return true;
7307 }();
7310 @safe unittest
7312 static assert(isTypeTuple!(int, float, string));
7313 static assert(!isTypeTuple!(1, 2.0, "a"));
7314 static assert(!isTypeTuple!(1, double, string));
7317 @safe unittest
7319 class C {}
7320 void func(int) {}
7321 auto c = new C;
7322 enum CONST = 42;
7324 static assert( isTypeTuple!int);
7325 static assert( isTypeTuple!string);
7326 static assert( isTypeTuple!C);
7327 static assert( isTypeTuple!(typeof(func)));
7328 static assert( isTypeTuple!(int, char, double));
7330 static assert(!isTypeTuple!c);
7331 static assert(!isTypeTuple!isTypeTuple);
7332 static assert(!isTypeTuple!CONST);
7337 Detect whether symbol or type `T` is a function pointer.
7339 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7342 @safe unittest
7344 static void foo() {}
7345 void bar() {}
7347 auto fpfoo = &foo;
7348 static assert( isFunctionPointer!fpfoo);
7349 static assert( isFunctionPointer!(void function()));
7351 auto dgbar = &bar;
7352 static assert(!isFunctionPointer!dgbar);
7353 static assert(!isFunctionPointer!(void delegate()));
7354 static assert(!isFunctionPointer!foo);
7355 static assert(!isFunctionPointer!bar);
7357 static assert( isFunctionPointer!((int a) {}));
7361 Detect whether symbol or type `T` is a delegate.
7363 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7366 @safe unittest
7368 static void sfunc() { }
7369 int x;
7370 void func() { x++; }
7372 int delegate() dg;
7373 assert(isDelegate!dg);
7374 assert(isDelegate!(int delegate()));
7375 assert(isDelegate!(typeof(&func)));
7377 int function() fp;
7378 assert(!isDelegate!fp);
7379 assert(!isDelegate!(int function()));
7380 assert(!isDelegate!(typeof(&sfunc)));
7384 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7386 Params:
7387 T = The type to check
7388 Returns:
7389 A `bool`
7391 template isSomeFunction(alias T)
7393 static if (is(typeof(& T) U : U*) && is(U == function) || is(typeof(& T) U == delegate))
7395 // T is a (nested) function symbol.
7396 enum bool isSomeFunction = true;
7398 else static if (is(T W) || is(typeof(T) W))
7400 // T is an expression or a type. Take the type of it and examine.
7401 static if (is(W F : F*) && is(F == function))
7402 enum bool isSomeFunction = true; // function pointer
7403 else
7404 enum bool isSomeFunction = is(W == function) || is(W == delegate);
7406 else
7407 enum bool isSomeFunction = false;
7411 @safe unittest
7413 static real func(ref int) { return 0; }
7414 static void prop() @property { }
7415 class C
7417 real method(ref int) { return 0; }
7418 real prop() @property { return 0; }
7420 auto c = new C;
7421 auto fp = &func;
7422 auto dg = &c.method;
7423 real val;
7425 static assert( isSomeFunction!func);
7426 static assert( isSomeFunction!prop);
7427 static assert( isSomeFunction!(C.method));
7428 static assert( isSomeFunction!(C.prop));
7429 static assert( isSomeFunction!(c.prop));
7430 static assert( isSomeFunction!(c.prop));
7431 static assert( isSomeFunction!fp);
7432 static assert( isSomeFunction!dg);
7434 static assert(!isSomeFunction!int);
7435 static assert(!isSomeFunction!val);
7438 @safe unittest
7440 void nestedFunc() { }
7441 void nestedProp() @property { }
7442 static assert(isSomeFunction!nestedFunc);
7443 static assert(isSomeFunction!nestedProp);
7444 static assert(isSomeFunction!(real function(ref int)));
7445 static assert(isSomeFunction!(real delegate(ref int)));
7446 static assert(isSomeFunction!((int a) { return a; }));
7447 static assert(!isSomeFunction!isSomeFunction);
7451 Detect whether `T` is a callable object, which can be called with the
7452 function call operator `$(LPAREN)...$(RPAREN)`.
7454 template isCallable(alias callable)
7456 static if (is(typeof(&callable.opCall) == delegate))
7457 // T is a object which has a member function opCall().
7458 enum bool isCallable = true;
7459 else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7460 // T is a type which has a static member function opCall().
7461 enum bool isCallable = true;
7462 else static if (is(typeof(&callable.opCall!())))
7464 alias TemplateInstanceType = typeof(&callable.opCall!());
7465 enum bool isCallable = isCallable!TemplateInstanceType;
7467 else static if (is(typeof(&callable!())))
7469 alias TemplateInstanceType = typeof(&callable!());
7470 enum bool isCallable = isCallable!TemplateInstanceType;
7472 else
7474 enum bool isCallable = isSomeFunction!callable;
7478 /// Functions, lambdas, and aggregate types with (static) opCall.
7479 @safe unittest
7481 void f() { }
7482 int g(int x) { return x; }
7484 static assert( isCallable!f);
7485 static assert( isCallable!g);
7487 class C { int opCall(int) { return 0; } }
7488 auto c = new C;
7489 struct S { static int opCall(int) { return 0; } }
7490 interface I { real value() @property; }
7492 static assert( isCallable!c);
7493 static assert( isCallable!(c.opCall));
7494 static assert( isCallable!S);
7495 static assert( isCallable!(I.value));
7496 static assert( isCallable!((int a) { return a; }));
7498 static assert(!isCallable!I);
7501 /// Templates
7502 @safe unittest
7504 void f()() { }
7505 T g(T = int)(T x) { return x; }
7506 struct S1 { static void opCall()() { } }
7507 struct S2 { static T opCall(T = int)(T x) {return x; } }
7509 static assert( isCallable!f);
7510 static assert( isCallable!g);
7511 static assert( isCallable!S1);
7512 static assert( isCallable!S2);
7515 /// Overloaded functions and function templates.
7516 @safe unittest
7518 static struct Wrapper
7520 void f() { }
7521 int f(int x) { return x; }
7523 void g()() { }
7524 T g(T = int)(T x) { return x; }
7527 static assert(isCallable!(Wrapper.f));
7528 static assert(isCallable!(Wrapper.g));
7533 Detect whether `T` is an abstract function.
7535 Params:
7536 T = The type to check
7537 Returns:
7538 A `bool`
7540 enum isAbstractFunction(alias T) = __traits(isAbstractFunction, T);
7543 @safe unittest
7545 struct S { void foo() { } }
7546 class C { void foo() { } }
7547 class AC { abstract void foo(); }
7548 static assert(!isAbstractFunction!(int));
7549 static assert(!isAbstractFunction!(S.foo));
7550 static assert(!isAbstractFunction!(C.foo));
7551 static assert( isAbstractFunction!(AC.foo));
7555 * Detect whether `T` is a final function.
7557 enum isFinalFunction(alias T) = __traits(isFinalFunction, T);
7560 @safe unittest
7562 struct S { void bar() { } }
7563 final class FC { void foo(); }
7564 class C
7566 void bar() { }
7567 final void foo();
7569 static assert(!isFinalFunction!(int));
7570 static assert(!isFinalFunction!(S.bar));
7571 static assert( isFinalFunction!(FC.foo));
7572 static assert(!isFinalFunction!(C.bar));
7573 static assert( isFinalFunction!(C.foo));
7577 Determines if `f` is a function that requires a context pointer.
7579 Params:
7580 f = The type to check
7581 Returns
7582 A `bool`
7584 template isNestedFunction(alias f)
7586 enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7590 @safe unittest
7592 static void f() {}
7593 static void fun()
7595 int i;
7596 int f() { return i; }
7598 static assert(isNestedFunction!(f));
7601 static assert(!isNestedFunction!f);
7604 // https://issues.dlang.org/show_bug.cgi?id=18669
7605 @safe unittest
7607 static class Outer
7609 class Inner
7613 int i;
7614 struct SS
7616 int bar() { return i; }
7618 static assert(!isNestedFunction!(Outer.Inner));
7619 static assert(!isNestedFunction!(SS));
7623 * Detect whether `T` is an abstract class.
7625 enum isAbstractClass(alias T) = __traits(isAbstractClass, T);
7628 @safe unittest
7630 struct S { }
7631 class C { }
7632 abstract class AC { }
7633 static assert(!isAbstractClass!S);
7634 static assert(!isAbstractClass!C);
7635 static assert( isAbstractClass!AC);
7636 C c;
7637 static assert(!isAbstractClass!c);
7638 AC ac;
7639 static assert( isAbstractClass!ac);
7643 * Detect whether `T` is a final class.
7645 enum isFinalClass(alias T) = __traits(isFinalClass, T);
7648 @safe unittest
7650 class C { }
7651 abstract class AC { }
7652 final class FC1 : C { }
7653 final class FC2 { }
7654 static assert(!isFinalClass!C);
7655 static assert(!isFinalClass!AC);
7656 static assert( isFinalClass!FC1);
7657 static assert( isFinalClass!FC2);
7658 C c;
7659 static assert(!isFinalClass!c);
7660 FC1 fc1;
7661 static assert( isFinalClass!fc1);
7664 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7665 // General Types
7666 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7668 version (StdDdoc)
7671 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7673 template Unconst(T)
7675 import core.internal.traits : CoreUnconst = Unconst;
7676 alias Unconst = CoreUnconst!(T);
7679 else
7681 import core.internal.traits : CoreUnconst = Unconst;
7682 alias Unconst = CoreUnconst;
7686 @safe unittest
7688 static assert(is(Unconst!int == int));
7689 static assert(is(Unconst!(const int) == int));
7690 static assert(is(Unconst!(immutable int) == int));
7691 static assert(is(Unconst!(shared int) == shared int));
7692 static assert(is(Unconst!(shared(const int)) == shared int));
7695 @safe unittest
7697 static assert(is(Unconst!( int) == int));
7698 static assert(is(Unconst!( const int) == int));
7699 static assert(is(Unconst!( inout int) == int));
7700 static assert(is(Unconst!( inout const int) == int));
7701 static assert(is(Unconst!(shared int) == shared int));
7702 static assert(is(Unconst!(shared const int) == shared int));
7703 static assert(is(Unconst!(shared inout int) == shared int));
7704 static assert(is(Unconst!(shared inout const int) == shared int));
7705 static assert(is(Unconst!( immutable int) == int));
7707 alias ImmIntArr = immutable(int[]);
7708 static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7711 version (StdDdoc)
7714 Removes all qualifiers, if any, from type `T`.
7716 template Unqual(T)
7718 import core.internal.traits : CoreUnqual = Unqual;
7719 alias Unqual = CoreUnqual!(T);
7722 else
7724 import core.internal.traits : CoreUnqual = Unqual;
7725 alias Unqual = CoreUnqual;
7729 @safe unittest
7731 static assert(is(Unqual!int == int));
7732 static assert(is(Unqual!(const int) == int));
7733 static assert(is(Unqual!(immutable int) == int));
7734 static assert(is(Unqual!(shared int) == int));
7735 static assert(is(Unqual!(shared(const int)) == int));
7738 @safe unittest
7740 static assert(is(Unqual!( int) == int));
7741 static assert(is(Unqual!( const int) == int));
7742 static assert(is(Unqual!( inout int) == int));
7743 static assert(is(Unqual!( inout const int) == int));
7744 static assert(is(Unqual!(shared int) == int));
7745 static assert(is(Unqual!(shared const int) == int));
7746 static assert(is(Unqual!(shared inout int) == int));
7747 static assert(is(Unqual!(shared inout const int) == int));
7748 static assert(is(Unqual!( immutable int) == int));
7750 alias ImmIntArr = immutable(int[]);
7751 static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7754 // [For internal use]
7755 package template ModifyTypePreservingTQ(alias Modifier, T)
7757 import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7758 alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7762 * Copies type qualifiers from `FromType` to `ToType`.
7764 * Supported type qualifiers:
7765 * $(UL
7766 * $(LI `const`)
7767 * $(LI `inout`)
7768 * $(LI `immutable`)
7769 * $(LI `shared`)
7772 template CopyTypeQualifiers(FromType, ToType)
7774 alias T(U) = ToType;
7775 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7779 @safe unittest
7781 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7784 @safe unittest
7786 static assert(is(CopyTypeQualifiers!( real, int) == int));
7787 static assert(is(CopyTypeQualifiers!( const real, int) == const int));
7788 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int));
7789 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int));
7790 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int));
7791 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int));
7792 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int));
7793 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
7794 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int));
7798 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
7799 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
7800 returned type will be the same as `ToType`.
7802 template CopyConstness(FromType, ToType)
7804 alias Unshared(T) = T;
7805 alias Unshared(T: shared U, U) = U;
7807 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
7811 @safe unittest
7813 const(int) i;
7814 CopyConstness!(typeof(i), float) f;
7815 assert( is(typeof(f) == const float));
7817 CopyConstness!(char, uint) u;
7818 assert( is(typeof(u) == uint));
7820 //The 'shared' qualifier will not be copied
7821 assert(!is(CopyConstness!(shared bool, int) == shared int));
7823 //But the constness will be
7824 assert( is(CopyConstness!(shared const real, double) == const double));
7826 //Careful, const(int)[] is a mutable array of const(int)
7827 alias MutT = CopyConstness!(const(int)[], int);
7828 assert(!is(MutT == const(int)));
7830 //Okay, const(int[]) applies to array and contained ints
7831 alias CstT = CopyConstness!(const(int[]), int);
7832 assert( is(CstT == const(int)));
7835 @safe unittest
7837 struct Test
7839 void method1() {}
7840 void method2() const {}
7841 void method3() immutable {}
7844 assert(is(CopyConstness!(typeof(Test.method1), real) == real));
7846 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
7848 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
7851 @safe unittest
7853 assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
7854 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
7857 @safe unittest
7859 static assert(is(CopyConstness!( int, real) == real));
7860 static assert(is(CopyConstness!(const int, real) == const real));
7861 static assert(is(CopyConstness!(inout int, real) == inout real));
7862 static assert(is(CopyConstness!(inout const int, real) == inout const real));
7863 static assert(is(CopyConstness!(shared int, real) == real));
7864 static assert(is(CopyConstness!(shared const int, real) == const real));
7865 static assert(is(CopyConstness!(shared inout int, real) == inout real));
7866 static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
7867 static assert(is(CopyConstness!(immutable int, real) == immutable real));
7871 Returns the inferred type of the loop variable when a variable of type T
7872 is iterated over using a `foreach` loop with a single loop variable and
7873 automatically inferred return type. Note that this may not be the same as
7874 `std.range.ElementType!Range` in the case of narrow strings, or if T
7875 has both opApply and a range interface.
7877 template ForeachType(T)
7879 alias ForeachType = ReturnType!(typeof(
7880 (inout int x = 0)
7882 foreach (elem; T.init)
7884 return elem;
7886 assert(0);
7887 }));
7891 @safe unittest
7893 static assert(is(ForeachType!(uint[]) == uint));
7894 static assert(is(ForeachType!string == immutable(char)));
7895 static assert(is(ForeachType!(string[string]) == string));
7896 static assert(is(ForeachType!(inout(int)[]) == inout(int)));
7901 * Strips off all `enum`s from type `T`.
7903 template OriginalType(T)
7905 import core.internal.traits : _OriginalType = OriginalType;
7906 alias OriginalType = _OriginalType!T;
7910 @safe unittest
7912 enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
7913 enum F : E { a = E.a }
7914 alias G = const(F);
7915 static assert(is(OriginalType!E == real));
7916 static assert(is(OriginalType!F == real));
7917 static assert(is(OriginalType!G == const real));
7921 * Get the Key type of an Associative Array.
7923 alias KeyType(V : V[K], K) = K;
7926 @safe unittest
7928 alias Hash = int[string];
7929 static assert(is(KeyType!Hash == string));
7930 static assert(is(ValueType!Hash == int));
7931 KeyType!Hash str = "a"; // str is declared as string
7932 ValueType!Hash num = 1; // num is declared as int
7936 * Get the Value type of an Associative Array.
7938 alias ValueType(V : V[K], K) = V;
7941 @safe unittest
7943 alias Hash = int[string];
7944 static assert(is(KeyType!Hash == string));
7945 static assert(is(ValueType!Hash == int));
7946 KeyType!Hash str = "a"; // str is declared as string
7947 ValueType!Hash num = 1; // num is declared as int
7951 Params:
7952 T = A built in integral or vector type.
7954 Returns:
7955 The corresponding unsigned numeric type for `T` with the
7956 same type qualifiers.
7958 If `T` is not a integral or vector, a compile-time error is given.
7960 template Unsigned(T)
7962 template Impl(T)
7964 static if (is(T : __vector(V[N]), V, size_t N))
7965 alias Impl = __vector(Impl!V[N]);
7966 else static if (isUnsigned!T)
7967 alias Impl = T;
7968 else static if (isSigned!T && !isFloatingPoint!T)
7970 static if (is(T == byte )) alias Impl = ubyte;
7971 static if (is(T == short)) alias Impl = ushort;
7972 static if (is(T == int )) alias Impl = uint;
7973 static if (is(T == long )) alias Impl = ulong;
7974 static if (is(ucent) && is(T == cent )) alias Impl = ucent;
7976 else
7977 static assert(false, "Type " ~ T.stringof ~
7978 " does not have an Unsigned counterpart");
7981 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
7985 @safe unittest
7987 static assert(is(Unsigned!(int) == uint));
7988 static assert(is(Unsigned!(long) == ulong));
7989 static assert(is(Unsigned!(const short) == const ushort));
7990 static assert(is(Unsigned!(immutable byte) == immutable ubyte));
7991 static assert(is(Unsigned!(inout int) == inout uint));
7995 /// Unsigned types are forwarded
7996 @safe unittest
7998 static assert(is(Unsigned!(uint) == uint));
7999 static assert(is(Unsigned!(const uint) == const uint));
8001 static assert(is(Unsigned!(ubyte) == ubyte));
8002 static assert(is(Unsigned!(immutable uint) == immutable uint));
8005 @safe unittest
8007 alias U1 = Unsigned!int;
8008 alias U2 = Unsigned!(const(int));
8009 alias U3 = Unsigned!(immutable(int));
8010 static assert(is(U1 == uint));
8011 static assert(is(U2 == const(uint)));
8012 static assert(is(U3 == immutable(uint)));
8013 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8015 alias UV1 = Unsigned!(__vector(int[4]));
8016 alias UV2 = Unsigned!(const(__vector(int[4])));
8017 static assert(is(UV1 == __vector(uint[4])));
8018 static assert(is(UV2 == const(__vector(uint[4]))));
8020 //struct S {}
8021 //alias U2 = Unsigned!S;
8022 //alias U3 = Unsigned!double;
8023 static if (is(ucent))
8025 alias U4 = Unsigned!cent;
8026 alias U5 = Unsigned!(const(cent));
8027 alias U6 = Unsigned!(immutable(cent));
8028 static assert(is(U4 == ucent));
8029 static assert(is(U5 == const(ucent)));
8030 static assert(is(U6 == immutable(ucent)));
8035 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
8036 than one type is of the same size, the leftmost argument of these in will be
8037 returned.
8039 template Largest(T...)
8040 if (T.length >= 1)
8042 alias Largest = T[0];
8043 static foreach (U; T[1 .. $])
8044 Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8048 @safe unittest
8050 static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8051 static assert(is(Largest!(ulong, double) == ulong));
8052 static assert(is(Largest!(double, ulong) == double));
8053 static assert(is(Largest!(uint, byte, double, short) == double));
8054 static if (is(ucent))
8055 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8059 Returns the corresponding signed type for T. T must be a numeric integral type,
8060 otherwise a compile-time error occurs.
8062 template Signed(T)
8064 template Impl(T)
8066 static if (is(T : __vector(V[N]), V, size_t N))
8067 alias Impl = __vector(Impl!V[N]);
8068 else static if (isSigned!T)
8069 alias Impl = T;
8070 else static if (isUnsigned!T)
8072 static if (is(T == ubyte )) alias Impl = byte;
8073 static if (is(T == ushort)) alias Impl = short;
8074 static if (is(T == uint )) alias Impl = int;
8075 static if (is(T == ulong )) alias Impl = long;
8076 static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8078 else
8079 static assert(false, "Type " ~ T.stringof ~
8080 " does not have an Signed counterpart");
8083 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8087 @safe unittest
8089 alias S1 = Signed!uint;
8090 static assert(is(S1 == int));
8091 alias S2 = Signed!(const(uint));
8092 static assert(is(S2 == const(int)));
8093 alias S3 = Signed!(immutable(uint));
8094 static assert(is(S3 == immutable(int)));
8095 static if (is(ucent))
8097 alias S4 = Signed!ucent;
8098 static assert(is(S4 == cent));
8102 @safe unittest
8104 static assert(is(Signed!float == float));
8105 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8107 alias SV1 = Signed!(__vector(uint[4]));
8108 alias SV2 = Signed!(const(__vector(uint[4])));
8109 static assert(is(SV1 == __vector(int[4])));
8110 static assert(is(SV2 == const(__vector(int[4]))));
8116 Returns the most negative value of the numeric type T.
8118 template mostNegative(T)
8119 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8121 static if (is(typeof(T.min_normal)))
8122 enum mostNegative = -T.max;
8123 else static if (T.min == 0)
8124 enum byte mostNegative = 0;
8125 else
8126 enum mostNegative = T.min;
8130 @safe unittest
8132 static assert(mostNegative!float == -float.max);
8133 static assert(mostNegative!double == -double.max);
8134 static assert(mostNegative!real == -real.max);
8135 static assert(mostNegative!bool == false);
8139 @safe unittest
8141 import std.meta : AliasSeq;
8143 static foreach (T; AliasSeq!(bool, byte, short, int, long))
8144 static assert(mostNegative!T == T.min);
8146 static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8147 static assert(mostNegative!T == 0);
8151 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8152 to in multi-term arithmetic expressions.
8154 template Promoted(T)
8155 if (isScalarType!T)
8157 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8161 @safe unittest
8163 ubyte a = 3, b = 5;
8164 static assert(is(typeof(a * b) == Promoted!ubyte));
8165 static assert(is(Promoted!ubyte == int));
8167 static assert(is(Promoted!(shared(bool)) == shared(int)));
8168 static assert(is(Promoted!(const(int)) == const(int)));
8169 static assert(is(Promoted!double == double));
8172 @safe unittest
8174 // promote to int:
8175 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8177 static assert(is(Promoted!T == int));
8178 static assert(is(Promoted!(shared(const T)) == shared(const int)));
8181 // already promoted:
8182 static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8184 static assert(is(Promoted!T == T));
8185 static assert(is(Promoted!(immutable(T)) == immutable(T)));
8189 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8190 // Misc.
8191 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8194 Returns the mangled name of symbol or type `sth`.
8196 `mangledName` is the same as builtin `.mangleof` property, but
8197 might be more convenient in generic code, e.g. as a template argument
8198 when invoking staticMap.
8200 enum mangledName(alias sth) = sth.mangleof;
8203 @safe unittest
8205 import std.meta : AliasSeq;
8206 alias TL = staticMap!(mangledName, int, const int, immutable int);
8207 static assert(TL == AliasSeq!("i", "xi", "yi"));
8210 version (StdUnittest) private void freeFunc(string);
8212 @safe unittest
8214 class C { int value() @property { return 0; } }
8215 static assert(mangledName!int == int.mangleof);
8216 static assert(mangledName!C == C.mangleof);
8217 static assert(mangledName!(C.value) == C.value.mangleof);
8218 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8219 static assert(mangledName!mangledName == "3std6traits11mangledName");
8220 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8221 int x;
8222 // https://issues.dlang.org/show_bug.cgi?id=9148
8223 static if (is(typeof({ return x; }) : int delegate() pure))
8224 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
8225 else
8226 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
8229 @system unittest
8231 // @system due to demangle
8232 // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8233 import std.demangle : demangle;
8234 int foo;
8235 auto foo_demangled = demangle(mangledName!foo);
8236 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8237 foo_demangled);
8239 void bar();
8240 auto bar_demangled = demangle(mangledName!bar);
8241 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8246 // XXX Select & select should go to another module. (functional or algorithm?)
8249 Aliases itself to `T[0]` if the boolean `condition` is `true`
8250 and to `T[1]` otherwise.
8252 template Select(bool condition, T...)
8253 if (T.length == 2)
8255 import std.meta : Alias;
8256 alias Select = Alias!(T[!condition]);
8260 @safe unittest
8262 // can select types
8263 static assert(is(Select!(true, int, long) == int));
8264 static assert(is(Select!(false, int, long) == long));
8265 static struct Foo {}
8266 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8268 // can select symbols
8269 int a = 1;
8270 int b = 2;
8271 alias selA = Select!(true, a, b);
8272 alias selB = Select!(false, a, b);
8273 assert(selA == 1);
8274 assert(selB == 2);
8276 // can select (compile-time) expressions
8277 enum val = Select!(false, -4, 9 - 6);
8278 static assert(val == 3);
8282 Select one of two functions to run via template parameter.
8284 Params:
8285 cond = A `bool` which determines which function is run
8286 a = The first function
8287 b = The second function
8289 Returns:
8290 `a` without evaluating `b` if `cond` is `true`.
8291 Otherwise, returns `b` without evaluating `a`.
8293 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8294 /// Ditto
8295 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8298 @safe unittest
8300 real run() { return 0; }
8301 int fail() { assert(0); }
8302 auto a = select!true(run(), fail());
8303 auto b = select!false(fail(), run());
8304 static assert(is(typeof(a) == real));
8305 static assert(is(typeof(b) == real));
8309 Determine if a symbol has a given
8310 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8312 See_Also:
8313 $(LREF getUDAs)
8315 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8318 @safe unittest
8320 enum E;
8321 struct S {}
8323 @("alpha") int a;
8324 static assert(hasUDA!(a, "alpha"));
8325 static assert(!hasUDA!(a, S));
8326 static assert(!hasUDA!(a, E));
8328 @(E) int b;
8329 static assert(!hasUDA!(b, "alpha"));
8330 static assert(!hasUDA!(b, S));
8331 static assert(hasUDA!(b, E));
8333 @E int c;
8334 static assert(!hasUDA!(c, "alpha"));
8335 static assert(!hasUDA!(c, S));
8336 static assert(hasUDA!(c, E));
8338 @(S, E) int d;
8339 static assert(!hasUDA!(d, "alpha"));
8340 static assert(hasUDA!(d, S));
8341 static assert(hasUDA!(d, E));
8343 @S int e;
8344 static assert(!hasUDA!(e, "alpha"));
8345 static assert(hasUDA!(e, S));
8346 static assert(!hasUDA!(e, S()));
8347 static assert(!hasUDA!(e, E));
8349 @S() int f;
8350 static assert(!hasUDA!(f, "alpha"));
8351 static assert(hasUDA!(f, S));
8352 static assert(hasUDA!(f, S()));
8353 static assert(!hasUDA!(f, E));
8355 @(S, E, "alpha") int g;
8356 static assert(hasUDA!(g, "alpha"));
8357 static assert(hasUDA!(g, S));
8358 static assert(hasUDA!(g, E));
8360 @(100) int h;
8361 static assert(hasUDA!(h, 100));
8363 struct Named { string name; }
8365 @Named("abc") int i;
8366 static assert(hasUDA!(i, Named));
8367 static assert(hasUDA!(i, Named("abc")));
8368 static assert(!hasUDA!(i, Named("def")));
8370 struct AttrT(T)
8372 string name;
8373 T value;
8376 @AttrT!int("answer", 42) int j;
8377 static assert(hasUDA!(j, AttrT));
8378 static assert(hasUDA!(j, AttrT!int));
8379 static assert(!hasUDA!(j, AttrT!string));
8381 @AttrT!string("hello", "world") int k;
8382 static assert(hasUDA!(k, AttrT));
8383 static assert(!hasUDA!(k, AttrT!int));
8384 static assert(hasUDA!(k, AttrT!string));
8386 struct FuncAttr(alias f) { alias func = f; }
8387 static int fourtyTwo() { return 42; }
8388 static size_t getLen(string s) { return s.length; }
8390 @FuncAttr!getLen int l;
8391 static assert(hasUDA!(l, FuncAttr));
8392 static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8393 static assert(hasUDA!(l, FuncAttr!getLen));
8394 static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8395 static assert(!hasUDA!(l, FuncAttr!getLen()));
8397 @FuncAttr!getLen() int m;
8398 static assert(hasUDA!(m, FuncAttr));
8399 static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8400 static assert(hasUDA!(m, FuncAttr!getLen));
8401 static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8402 static assert(hasUDA!(m, FuncAttr!getLen()));
8406 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8407 from the given symbol.
8409 If the UDA is a type, then any UDAs of the same type on the symbol will
8410 match. If the UDA is a template for a type, then any UDA which is an
8411 instantiation of that template will match. And if the UDA is a value,
8412 then any UDAs on the symbol which are equal to that value will match.
8414 See_Also:
8415 $(LREF hasUDA)
8417 template getUDAs(alias symbol, alias attribute)
8419 import std.meta : Filter;
8421 alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8425 @safe unittest
8427 struct Attr
8429 string name;
8430 int value;
8433 @Attr("Answer", 42) int a;
8434 static assert(getUDAs!(a, Attr).length == 1);
8435 static assert(getUDAs!(a, Attr)[0].name == "Answer");
8436 static assert(getUDAs!(a, Attr)[0].value == 42);
8438 @(Attr("Answer", 42), "string", 9999) int b;
8439 static assert(getUDAs!(b, Attr).length == 1);
8440 static assert(getUDAs!(b, Attr)[0].name == "Answer");
8441 static assert(getUDAs!(b, Attr)[0].value == 42);
8443 @Attr("Answer", 42) @Attr("Pi", 3) int c;
8444 static assert(getUDAs!(c, Attr).length == 2);
8445 static assert(getUDAs!(c, Attr)[0].name == "Answer");
8446 static assert(getUDAs!(c, Attr)[0].value == 42);
8447 static assert(getUDAs!(c, Attr)[1].name == "Pi");
8448 static assert(getUDAs!(c, Attr)[1].value == 3);
8450 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8451 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8452 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8454 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8456 struct AttrT(T)
8458 string name;
8459 T value;
8462 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8463 static assert(getUDAs!(d, AttrT).length == 2);
8464 static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8465 static assert(getUDAs!(d, AttrT)[0].value == 42);
8466 static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8467 static assert(getUDAs!(d, AttrT)[1].value == 3);
8469 static assert(getUDAs!(d, AttrT!uint).length == 1);
8470 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8471 static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8473 static assert(getUDAs!(d, AttrT!int).length == 1);
8474 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8475 static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8477 struct SimpleAttr {}
8479 @SimpleAttr int e;
8480 static assert(getUDAs!(e, SimpleAttr).length == 1);
8481 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8483 @SimpleAttr() int f;
8484 static assert(getUDAs!(f, SimpleAttr).length == 1);
8485 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8487 struct FuncAttr(alias f) { alias func = f; }
8488 static int add42(int v) { return v + 42; }
8489 static string concat(string l, string r) { return l ~ r; }
8491 @FuncAttr!add42 int g;
8492 static assert(getUDAs!(g, FuncAttr).length == 1);
8493 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8495 static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8496 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8498 static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8500 static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8501 static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8503 @FuncAttr!add42() int h;
8504 static assert(getUDAs!(h, FuncAttr).length == 1);
8505 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8507 static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8508 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8510 static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8511 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8513 static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8514 static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8516 @("alpha") @(42) int i;
8517 static assert(getUDAs!(i, "alpha").length == 1);
8518 static assert(getUDAs!(i, "alpha")[0] == "alpha");
8520 static assert(getUDAs!(i, 42).length == 1);
8521 static assert(getUDAs!(i, 42)[0] == 42);
8523 static assert(getUDAs!(i, 'c').length == 0);
8526 private template isDesiredUDA(alias attribute)
8528 template isDesiredUDA(alias toCheck)
8530 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8532 static if (__traits(compiles, toCheck == attribute))
8533 enum isDesiredUDA = toCheck == attribute;
8534 else
8535 enum isDesiredUDA = false;
8537 else static if (is(typeof(toCheck)))
8539 static if (__traits(isTemplate, attribute))
8540 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck));
8541 else
8542 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8544 else static if (__traits(isTemplate, attribute))
8545 enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8546 else
8547 enum isDesiredUDA = is(toCheck == attribute);
8552 Params:
8553 symbol = The aggregate type or module to search
8554 attribute = The user-defined attribute to search for
8556 Returns:
8557 All symbols within `symbol` that have the given UDA `attribute`.
8559 Note:
8560 This is not recursive; it will not search for symbols within symbols such as
8561 nested structs or unions.
8563 template getSymbolsByUDA(alias symbol, alias attribute)
8565 alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8567 // if the symbol itself has the UDA, tack it on to the front of the list
8568 static if (hasUDA!(symbol, attribute))
8569 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8570 else
8571 alias getSymbolsByUDA = membersWithUDA;
8575 @safe unittest
8577 enum Attr;
8578 struct A
8580 @Attr int a;
8581 int b;
8584 static assert(getSymbolsByUDA!(A, Attr).length == 1);
8585 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8589 @safe unittest
8591 enum Attr;
8593 static struct A
8595 @Attr int a;
8596 int b;
8597 @Attr void doStuff() {}
8598 void doOtherStuff() {}
8599 static struct Inner
8601 // Not found by getSymbolsByUDA
8602 @Attr int c;
8606 // Finds both variables and functions with the attribute, but
8607 // doesn't include the variables and functions without it.
8608 static assert(getSymbolsByUDA!(A, Attr).length == 2);
8609 // Can access attributes on the symbols returned by getSymbolsByUDA.
8610 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8611 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8614 /// Finds multiple attributes
8615 @safe unittest
8617 static struct UDA { string name; }
8619 static struct B
8621 @UDA("X")
8622 int x;
8623 @UDA("Y")
8624 int y;
8625 @(100)
8626 int z;
8629 // Finds both UDA attributes.
8630 static assert(getSymbolsByUDA!(B, UDA).length == 2);
8631 // Finds one `100` attribute.
8632 static assert(getSymbolsByUDA!(B, 100).length == 1);
8633 // Can get the value of the UDA from the return value
8634 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8637 /// Checks for UDAs on the aggregate symbol itself
8638 @safe unittest
8640 static struct UDA { string name; }
8642 @UDA("A")
8643 static struct C
8645 @UDA("B")
8646 int d;
8649 static assert(getSymbolsByUDA!(C, UDA).length == 2);
8650 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8651 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8654 /// Finds nothing if there is no member with specific UDA
8655 @safe unittest
8657 static struct UDA { string name; }
8659 static struct D
8661 int x;
8664 static assert(getSymbolsByUDA!(D, UDA).length == 0);
8667 // https://issues.dlang.org/show_bug.cgi?id=18314
8668 @safe unittest
8670 enum attr1;
8671 enum attr2;
8673 struct A
8675 @attr1
8676 int n;
8677 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8678 //@attr1
8679 //void foo()(string){}
8680 @attr1
8681 void foo();
8682 @attr2
8683 void foo(int a);
8686 static assert(getSymbolsByUDA!(A, attr1).length == 2);
8687 static assert(getSymbolsByUDA!(A, attr2).length == 1);
8690 // getSymbolsByUDA fails if type has private members
8691 // https://issues.dlang.org/show_bug.cgi?id=15335
8692 @safe unittest
8694 // HasPrivateMembers has, well, private members, one of which has a UDA.
8695 import std.internal.test.uda : Attr, HasPrivateMembers;
8696 // Trying access to private member from another file therefore we do not have access
8697 // for this otherwise we get deprecation warning - not visible from module
8698 // This line is commented because `__traits(getMember)` should also consider
8699 // private members; this is not currently the case, but the PR that
8700 // fixes `__traits(getMember)` is blocked by this specific test.
8701 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8702 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8705 // getSymbolsByUDA works with structs but fails with classes
8706 // https://issues.dlang.org/show_bug.cgi?id=16387
8707 @safe unittest
8709 enum Attr;
8710 class A
8712 @Attr uint a;
8715 alias res = getSymbolsByUDA!(A, Attr);
8716 static assert(res.length == 1);
8717 static assert(res[0].stringof == "a");
8720 // getSymbolsByUDA fails on AliasSeq members
8721 // https://issues.dlang.org/show_bug.cgi?id=18884
8722 @safe unittest
8724 struct X
8726 alias A = AliasSeq!(ulong, uint);
8729 static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8732 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8733 // https://issues.dlang.org/show_bug.cgi?id=18624
8734 @safe unittest
8736 enum Attr;
8737 struct A
8739 @Attr void a();
8740 @Attr void a(int n);
8741 void b();
8742 @Attr void c();
8745 static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)");
8748 // getSymbolsByUDA no longer works on modules
8749 // https://issues.dlang.org/show_bug.cgi?id=20054
8750 version (StdUnittest)
8752 @("Issue20054")
8753 void issue20054() {}
8754 static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8757 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8759 import std.meta : Alias, AliasSeq, Filter;
8760 static if (names.length == 0)
8762 alias getSymbolsByUDAImpl = AliasSeq!();
8764 else
8766 alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
8768 // Filtering inaccessible members.
8769 static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
8771 alias getSymbolsByUDAImpl = tail;
8773 else
8775 alias member = __traits(getMember, symbol, names[0]);
8777 // Filtering not compiled members such as alias of basic types.
8778 static if (!__traits(compiles, hasUDA!(member, attribute)))
8780 alias getSymbolsByUDAImpl = tail;
8782 // Get overloads for functions, in case different overloads have different sets of UDAs.
8783 else static if (isFunction!member)
8785 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
8786 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
8787 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
8789 else static if (hasUDA!(member, attribute))
8791 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
8793 else
8795 alias getSymbolsByUDAImpl = tail;
8802 Returns: `true` iff all types `Ts` are the same.
8804 enum bool allSameType(Ts...) =
8806 static foreach (T; Ts[Ts.length > 1 .. $])
8807 static if (!is(Ts[0] == T))
8808 if (__ctfe) // Dodge the "statement is unreachable" warning
8809 return false;
8810 return true;
8811 }();
8814 @safe unittest
8816 static assert(allSameType!());
8817 static assert(allSameType!(int));
8818 static assert(allSameType!(int, int));
8819 static assert(allSameType!(int, int, int));
8820 static assert(allSameType!(float, float, float));
8821 static assert(!allSameType!(int, double));
8822 static assert(!allSameType!(int, float, double));
8823 static assert(!allSameType!(int, float, double, real));
8824 static assert(!allSameType!(short, int, float, double, real));
8828 Returns: `true` iff the type `T` can be tested in an $(D
8829 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
8831 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
8833 @safe unittest
8835 import std.meta : AliasSeq, allSatisfy;
8836 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
8837 struct BoolWrapper { bool value; }
8838 static assert(!ifTestable!(bool, a => BoolWrapper(a)));
8842 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
8843 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
8845 * Returns:
8846 * `true` if `X` is a type, `false` otherwise
8848 enum isType(alias X) = is(X);
8851 @safe unittest
8853 struct S {
8854 template Test() {}
8856 class C {}
8857 interface I {}
8858 union U {}
8859 static assert(isType!int);
8860 static assert(isType!string);
8861 static assert(isType!(int[int]));
8862 static assert(isType!S);
8863 static assert(isType!C);
8864 static assert(isType!I);
8865 static assert(isType!U);
8867 int n;
8868 void func(){}
8869 static assert(!isType!n);
8870 static assert(!isType!func);
8871 static assert(!isType!(S.Test));
8872 static assert(!isType!(S.Test!()));
8876 * Detect whether symbol or type `X` is a function. This is different that finding
8877 * if a symbol is callable or satisfying `is(X == function)`, it finds
8878 * specifically if the symbol represents a normal function declaration, i.e.
8879 * not a delegate or a function pointer.
8881 * Returns:
8882 * `true` if `X` is a function, `false` otherwise
8884 * See_Also:
8885 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
8886 * respectively.
8888 template isFunction(alias X)
8890 static if (is(typeof(&X) U : U*) && is(U == function) ||
8891 is(typeof(&X) U == delegate))
8893 // x is a (nested) function symbol.
8894 enum isFunction = true;
8896 else static if (is(X T))
8898 // x is a type. Take the type of it and examine.
8899 enum isFunction = is(T == function);
8901 else
8902 enum isFunction = false;
8906 @safe unittest
8908 static void func(){}
8909 static assert(isFunction!func);
8911 struct S
8913 void func(){}
8915 static assert(isFunction!(S.func));
8919 * Detect whether `X` is a final method or class.
8921 * Returns:
8922 * `true` if `X` is final, `false` otherwise
8924 template isFinal(alias X)
8926 static if (is(X == class))
8927 enum isFinal = __traits(isFinalClass, X);
8928 else static if (isFunction!X)
8929 enum isFinal = __traits(isFinalFunction, X);
8930 else
8931 enum isFinal = false;
8935 @safe unittest
8937 class C
8939 void nf() {}
8940 static void sf() {}
8941 final void ff() {}
8943 final class FC { }
8945 static assert(!isFinal!(C));
8946 static assert( isFinal!(FC));
8948 static assert(!isFinal!(C.nf));
8949 static assert(!isFinal!(C.sf));
8950 static assert( isFinal!(C.ff));
8954 + Determines whether the type `S` can be copied.
8955 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
8956 + Copying for structs can be disabled by using `@disable this(this)`.
8958 + Params:
8959 + S = The type to check.
8961 + Returns:
8962 + `true` if `S` can be copied. `false` otherwise.
8963 + ++/
8964 enum isCopyable(S) = __traits(isCopyable, S);
8967 @safe unittest
8969 struct S1 {} // Fine. Can be copied
8970 struct S2 { this(this) {}} // Fine. Can be copied
8971 struct S3 {@disable this(this); } // Not fine. Copying is disabled.
8972 struct S4 {S3 s;} // Not fine. A field has copying disabled.
8974 class C1 {}
8976 static assert( isCopyable!S1);
8977 static assert( isCopyable!S2);
8978 static assert(!isCopyable!S3);
8979 static assert(!isCopyable!S4);
8981 static assert(isCopyable!C1);
8982 static assert(isCopyable!int);
8983 static assert(isCopyable!(int[]));