1 // Written in the D programming language.
4 * Templates which extract information about types and symbols at compile time.
6 * $(SCRIPT inhibitQuickIndex = 1;)
10 * $(TR $(TH Category) $(TH Templates))
11 * $(TR $(TD Symbol Name traits) $(TD
12 * $(LREF fullyQualifiedName)
17 * $(TR $(TD Function traits) $(TD
20 * $(LREF functionAttributes)
21 * $(LREF hasFunctionAttributes)
22 * $(LREF functionLinkage)
23 * $(LREF FunctionTypeOf)
27 * $(LREF ParameterDefaults)
28 * $(LREF ParameterIdentifierTuple)
29 * $(LREF ParameterStorageClassTuple)
32 * $(LREF SetFunctionAttributes)
33 * $(LREF variadicFunctionStyle)
35 * $(TR $(TD Aggregate Type traits) $(TD
36 * $(LREF BaseClassesTuple)
37 * $(LREF BaseTypeTuple)
38 * $(LREF classInstanceAlignment)
40 * $(LREF FieldNameTuple)
43 * $(LREF hasElaborateAssign)
44 * $(LREF hasElaborateCopyConstructor)
45 * $(LREF hasElaborateDestructor)
46 * $(LREF hasElaborateMove)
47 * $(LREF hasIndirections)
49 * $(LREF hasStaticMember)
51 * $(LREF hasUnsharedAliasing)
52 * $(LREF InterfacesTuple)
53 * $(LREF isInnerClass)
55 * $(LREF MemberFunctionsTuple)
56 * $(LREF RepresentationTypeTuple)
57 * $(LREF TemplateArgsOf)
59 * $(LREF TransitiveBaseTypeTuple)
61 * $(TR $(TD Type Conversion) $(TD
63 * $(LREF AllImplicitConversionTargets)
64 * $(LREF ImplicitConversionTargets)
65 * $(LREF CopyTypeQualifiers)
66 * $(LREF CopyConstness)
67 * $(LREF isAssignable)
68 * $(LREF isCovariantWith)
69 * $(LREF isImplicitlyConvertible)
71 * $(TR $(TD Type Constructors) $(TD
75 * $(LREF SharedInoutOf)
76 * $(LREF SharedConstOf)
77 * $(LREF SharedConstInoutOf)
81 * $(TR $(TD Categories of types) $(TD
85 * $(LREF isAggregateType)
87 * $(LREF isAssociativeArray)
88 * $(LREF isAutodecodableString)
91 * $(LREF isBuiltinType)
93 * $(LREF isDynamicArray)
94 * $(LREF isEqualityComparable)
95 * $(LREF isFloatingPoint)
97 * $(LREF isNarrowString)
98 * $(LREF isConvertibleToString)
100 * $(LREF isOrderingComparable)
102 * $(LREF isScalarType)
104 * $(LREF isSIMDVector)
106 * $(LREF isSomeString)
107 * $(LREF isStaticArray)
110 * $(TR $(TD Type behaviours) $(TD
111 * $(LREF isAbstractClass)
112 * $(LREF isAbstractFunction)
115 * $(LREF isExpressions)
116 * $(LREF isFinalClass)
117 * $(LREF isFinalFunction)
118 * $(LREF isFunctionPointer)
119 * $(LREF isInstanceOf)
122 * $(LREF isSomeFunction)
123 * $(LREF isTypeTuple)
125 * $(TR $(TD General Types) $(TD
126 * $(LREF ForeachType)
129 * $(LREF mostNegative)
130 * $(LREF OriginalType)
131 * $(LREF PointerTarget)
139 * $(TR $(TD Misc) $(TD
145 * $(TR $(TD User-Defined Attributes) $(TD
148 * $(LREF getSymbolsByUDA)
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),
159 * $(HTTP octarineparrot.com, Robert Clipsham),
160 * $(HTTP klickverbot.at, David Nadlinger),
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)
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 ///////////////////////////////////////////////////////////////////////////////
183 ///////////////////////////////////////////////////////////////////////////////
187 static if (is(ucent))
189 alias CentTypeList
= AliasSeq
!(cent, ucent);
190 alias SignedCentTypeList
= AliasSeq
!(cent);
191 alias UnsignedCentTypeList
= AliasSeq
!(ucent);
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);
212 * T = The type to qualify
214 * `T` with the `inout` qualifier added.
216 alias InoutOf(T
) = inout(T
);
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));
229 * T = The type to qualify
231 * `T` with the `const` qualifier added.
233 alias ConstOf(T
) = const(T
);
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));
246 * T = The type to qualify
248 * `T` with the `shared` qualifier added.
250 alias SharedOf(T
) = shared(T
);
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));
263 * T = The type to qualify
265 * `T` with the `inout` and `shared` qualifiers added.
267 alias SharedInoutOf(T
) = shared(inout(T
));
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));
281 * T = The type to qualify
283 * `T` with the `const` and `shared` qualifiers added.
285 alias SharedConstOf(T
) = shared(const(T
));
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));
300 * T = The type to qualify
302 * `T` with the `const`, `shared`, and `inout` qualifiers added.
304 alias SharedConstInoutOf(T
) = shared(const(inout(T
)));
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));
318 * T = The type to qualify
320 * `T` with the `immutable` qualifier added.
322 alias ImmutableOf(T
) = immutable(T
);
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));
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`.
349 * T = the type to check qualifiers from
351 * The qualifier template from the given type `T`
353 template QualifierOf(T
)
355 static if (is(immutable T
== T
))
357 alias QualifierOf
= ImmutableOf
;
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
;
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
));
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
);
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
);
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
;
429 static assert(false, T
.stringof
~ " has no parent");
435 static assert(packageName
!packageName
== "std");
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");
467 static assert(packageName
!moduleName
== "std");
470 // https://issues.dlang.org/show_bug.cgi?id=13741
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
~ '.';
501 enum packagePrefix
= "";
503 enum moduleName
= packagePrefix
~ T
.stringof
[7..$];
506 alias moduleName
= moduleName
!(parentOf
!T
); // If you use enum, it will cause compiler ICE
512 static assert(moduleName
!moduleName
== "std.traits");
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
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");
556 * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.
562 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
565 enum fullyQualifiedName(T
) = fqnType
!(T
, false, false, false, false);
568 enum fullyQualifiedName(alias T
) = fqnSym
!(T
);
573 static assert(fullyQualifiedName
!fullyQualifiedName
== "std.traits.fullyQualifiedName");
576 version (StdUnittest
)
578 // Used for both fqnType and fqnSym unittests
579 private struct QualifiedNameTests
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, ...);
597 void dVarArg2(int, ...);
598 void typesafeVarArg(int[] ...);
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
621 private template fqnSym(alias T
: X
!A
, alias X
, A
...)
623 template fqnTuple(T
...)
625 static if (T
.length
== 0)
627 else static if (T
.length
== 1)
629 static if (isExpressionTuple
!T
)
630 enum fqnTuple
= T
[0].stringof
;
632 enum fqnTuple
= fullyQualifiedName
!(T
[0]);
635 enum fqnTuple
= fqnTuple
!(T
[0]) ~ ", " ~ fqnTuple
!(T
[1 .. $]);
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
)) ~ ".";
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 "))
656 return s
.findSplit("(")[0];
658 enum fqnSym
= parentPrefix
~ adjustIdent(__traits(identifier
, T
));
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");
689 struct TemplatedStruct()
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
)
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
;
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
= " ...";
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
)])
759 return result
~= variadicStr
;
765 string
linkageString(T
)() @property
767 enum linkage
= functionLinkage
!T
;
770 return "extern(" ~ linkage
~ ") ";
775 string
functionAttributeString(T
)() @property
777 alias FA
= FunctionAttribute
;
778 enum attrs
= functionAttributes
!T
;
780 static if (attrs
== FA
.none
)
784 (attrs
& FA
.pure_ ?
" pure" : "")
785 ~ (attrs
& FA
.nothrow_ ?
" nothrow" : "")
786 ~ (attrs
& FA
.ref_ ?
" ref" : "")
787 ~ (attrs
& FA
.property ?
" @property" : "")
788 ~ (attrs
& FA
.trusted ?
" @trusted" : "")
789 ~ (attrs
& FA
.safe ?
" @safe" : "")
790 ~ (attrs
& FA
.nogc ?
" @nogc" : "")
791 ~ (attrs
& FA
.return_ ?
" return" : "")
792 ~ (attrs
& FA
.live ?
" @live" : "");
795 string
addQualifiers(string typeString
,
796 bool addConst
, bool addImmutable
, bool addShared
, bool addInout
)
798 auto result
= typeString
;
801 result
= "shared(" ~ result
~")";
803 if (addConst || addImmutable || addInout
)
805 result
= (addConst ?
"const" : addImmutable ?
"immutable" : "inout")
806 ~ "(" ~ result
~ ")";
811 // Convenience template to avoid copy-paste
812 template chain(string current
)
814 enum chain
= addQualifiers(current
,
815 qualifiers
[_const
] && !alreadyConst
,
816 qualifiers
[_immutable
] && !alreadyImmutable
,
817 qualifiers
[_shared
] && !alreadyShared
,
818 qualifiers
[_inout
] && !alreadyInout
);
821 static if (is(T
== string
))
823 enum fqnType
= "string";
825 else static if (is(T
== wstring
))
827 enum fqnType
= "wstring";
829 else static if (is(T
== dstring
))
831 enum fqnType
= "dstring";
833 else static if (is(T
== typeof(null)))
835 enum fqnType
= "typeof(null)";
837 else static if (isBasicType
!T
&& !is(T
== enum))
839 enum fqnType
= chain
!((Unqual
!T
).stringof
);
841 else static if (isAggregateType
!T ||
is(T
== enum))
843 enum fqnType
= chain
!(fqnSym
!T
);
845 else static if (isStaticArray
!T
)
847 import std
.conv
: to
;
848 enum fqnType
= chain
!(
849 fqnType
!(typeof(T
.init
[0]), qualifiers
) ~ "[" ~ to
!string(T
.length
) ~ "]"
852 else static if (isArray
!T
)
854 enum fqnType
= chain
!(
855 fqnType
!(typeof(T
.init
[0]), qualifiers
) ~ "[]"
858 else static if (isAssociativeArray
!T
)
860 enum fqnType
= chain
!(
861 fqnType
!(ValueType
!T
, qualifiers
) ~ '[' ~ fqnType
!(KeyType
!T
, noQualifiers
) ~ ']'
864 else static if (isSomeFunction
!T
)
866 static if (is(T F
== delegate))
868 enum qualifierString
=
869 (is(F
== shared) ?
" shared" : "")
870 ~ (is(F
== inout) ?
" inout" :
871 is(F
== immutable) ?
" immutable" :
872 is(F
== const) ?
" const" : "");
873 enum fqnType
= chain
!(
875 ~ fqnType
!(ReturnType
!T
, noQualifiers
)
876 ~ " delegate(" ~ parametersTypeString
!(T
) ~ ")"
877 ~ functionAttributeString
!T
883 enum fqnType
= chain
!(
885 ~ fqnType
!(ReturnType
!T
, noQualifiers
)
886 ~ (isFunctionPointer
!T ?
" function(" : "(")
887 ~ parametersTypeString
!(T
) ~ ")"
888 ~ functionAttributeString
!T
892 else static if (is(T
== U
*, U
))
894 enum fqnType
= chain
!(
895 fqnType
!(U
, qualifiers
) ~ "*"
898 else static if (is(T
: __vector(V
[N
]), V
, size_t N
))
900 import std
.conv
: to
;
901 enum fqnType
= chain
!(
902 "__vector(" ~ fqnType
!(V
, qualifiers
) ~ "[" ~ N
.to
!string
~ "])"
906 // In case something is forgotten
907 static assert(0, "Unrecognized type " ~ T
.stringof
~ ", can't convert to fully qualified string");
912 import std
.format
: format
;
913 alias fqn
= fullyQualifiedName
;
915 // Verify those 2 are the same for simple case
916 alias Ambiguous
= const(QualifiedNameTests
.Inner
);
917 static assert(fqn
!Ambiguous
== fqnType
!(Ambiguous
, false, false, false, false));
920 enum inner_name
= "std.traits.QualifiedNameTests.Inner";
921 with (QualifiedNameTests
)
924 static assert(fqn
!(string
) == "string");
925 static assert(fqn
!(wstring
) == "wstring");
926 static assert(fqn
!(dstring
) == "dstring");
927 static assert(fqn
!(typeof(null)) == "typeof(null)");
928 static assert(fqn
!(void) == "void");
929 static assert(fqn
!(const(void)) == "const(void)");
930 static assert(fqn
!(shared(void)) == "shared(void)");
931 static assert(fqn
!(shared const(void)) == "const(shared(void))");
932 static assert(fqn
!(shared inout(void)) == "inout(shared(void))");
933 static assert(fqn
!(shared inout const(void)) == "const(shared(void))");
934 static assert(fqn
!(inout(void)) == "inout(void)");
935 static assert(fqn
!(inout const(void)) == "const(void)");
936 static assert(fqn
!(immutable(void)) == "immutable(void)");
938 // Basic qualified name
939 static assert(fqn
!(Inner
) == inner_name
);
940 static assert(fqn
!(QualifiedEnum
) == "std.traits.QualifiedEnum"); // type
941 static assert(fqn
!(QualifiedEnum
.a
) == "std.traits.QualifiedEnum.a"); // symbol
944 static assert(fqn
!(typeof(array
)) == format("%s[]", inner_name
));
945 static assert(fqn
!(typeof(sarray
)) == format("%s[16]", inner_name
));
946 static assert(fqn
!(typeof(aarray
)) == format("%s[%s]", inner_name
, inner_name
));
948 // qualified key for AA
949 static assert(fqn
!(typeof(qualAarray
)) == format("const(%s[const(%s)])", inner_name
, inner_name
));
951 // Qualified composed data types
952 static assert(fqn
!(typeof(data
)) == format("shared(const(%s[string])[])", inner_name
));
954 // Function types + function attributes
955 static assert(fqn
!(typeof(func
)) == format("const(%s[string])(ref %s, scope lazy string) ref",
956 inner_name
, inner_name
));
957 static assert(fqn
!(typeof(retfunc
)) == format("const(%s[string])(return %s) ref", inner_name
, inner_name
));
958 static assert(fqn
!(typeof(inoutFunc
)) == format("inout(%s(inout(%s)))", inner_name
, inner_name
));
959 static assert(fqn
!(typeof(deleg
)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name
));
960 static assert(fqn
!(typeof(inoutDeleg
)) == "inout(int) delegate(inout(int)) inout");
961 static assert(fqn
!(typeof(funcPtr
)) == format("%s function(out double, string)", inner_name
));
962 static assert(fqn
!(typeof(cFuncPtr
)) == format("extern(C) %s function(double, string)", inner_name
));
964 // Delegate type with qualified function type
965 static assert(fqn
!(typeof(attrDeleg
)) == format("shared(immutable(%s) "~
966 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name
));
968 // Variable argument function types
969 static assert(fqn
!(typeof(cVarArg
)) == "extern(C) void(int, ...)");
970 static assert(fqn
!(typeof(dVarArg
)) == "void(...)");
971 static assert(fqn
!(typeof(dVarArg2
)) == "void(int, ...)");
972 static assert(fqn
!(typeof(typesafeVarArg
)) == "void(int[] ...)");
975 static if (is(__vector(float[4])))
977 static assert(fqn
!(__vector(float[4])) == "__vector(float[4])");
983 * Get the type of the return value from a function,
984 * a pointer to function, a delegate, a struct
985 * with an opCall, a pointer to a struct with an opCall,
986 * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
987 * is not part of a type, but the attribute of the function
988 * (see template $(LREF functionAttributes)).
990 * $(NOTE To reduce template instantiations, consider instead using
991 * $(D typeof(() { return func(args); } ())) if the argument types are known or
992 * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
994 template ReturnType(alias func
)
997 static if (is(FunctionTypeOf
!func R
== return))
998 alias ReturnType
= R
;
1000 static assert(0, "argument has no return type");
1007 ReturnType
!foo x
; // x is declared as int
1014 int opCall (int i
) { return 1;}
1017 alias ShouldBeInt
= ReturnType
!G
;
1018 static assert(is(ShouldBeInt
== int));
1021 static assert(is(ReturnType
!g
== int));
1024 alias pg
= ReturnType
!p
;
1025 static assert(is(pg
== int));
1029 int opCall (int i
) { return 1;}
1032 static assert(is(ReturnType
!C
== int));
1035 static assert(is(ReturnType
!c
== int));
1039 int prop() @property { return 0; }
1041 alias R_Test_prop
= ReturnType
!(Test
.prop
);
1042 static assert(is(R_Test_prop
== int));
1044 alias R_dglit
= ReturnType
!((int a
) { return a
; });
1045 static assert(is(R_dglit
== int));
1049 Get, as a tuple, the types of the parameters to a function, a pointer
1050 to function, a delegate, a struct with an `opCall`, a pointer to a
1051 struct with an `opCall`, or a class with an `opCall`.
1053 template Parameters(alias func
)
1054 if (isCallable
!func
)
1056 static if (is(FunctionTypeOf
!func P
== function))
1057 alias Parameters
= P
;
1059 static assert(0, "argument has no parameters");
1066 void bar(Parameters
!foo
); // declares void bar(int, long);
1067 void abc(Parameters
!foo
[1]); // declares void abc(long);
1071 * Alternate name for $(LREF Parameters), kept for legacy compatibility.
1073 alias ParameterTypeTuple
= Parameters
;
1077 int foo(int i
, bool b
) { return 0; }
1078 static assert(is(ParameterTypeTuple
!foo
== AliasSeq
!(int, bool)));
1079 static assert(is(ParameterTypeTuple
!(typeof(&foo
)) == AliasSeq
!(int, bool)));
1081 struct S
{ real opCall(real r
, int i
) { return 0.0; } }
1083 static assert(is(ParameterTypeTuple
!S
== AliasSeq
!(real, int)));
1084 static assert(is(ParameterTypeTuple
!(S
*) == AliasSeq
!(real, int)));
1085 static assert(is(ParameterTypeTuple
!s
== AliasSeq
!(real, int)));
1089 int prop() @property { return 0; }
1091 alias P_Test_prop
= ParameterTypeTuple
!(Test
.prop
);
1092 static assert(P_Test_prop
.length
== 0);
1094 alias P_dglit
= ParameterTypeTuple
!((int a
){});
1095 static assert(P_dglit
.length
== 1);
1096 static assert(is(P_dglit
[0] == int));
1100 Returns the number of arguments of function `func`.
1101 arity is undefined for variadic functions.
1103 template arity(alias func
)
1104 if (isCallable
!func
&& variadicFunctionStyle
!func
== Variadic
.no
)
1106 enum size_t arity
= Parameters
!func
.length
;
1113 static assert(arity
!foo
== 0);
1115 static assert(arity
!bar
== 1);
1116 void variadicFoo(uint...){}
1117 static assert(!__traits(compiles
, arity
!variadicFoo
));
1120 // https://issues.dlang.org/show_bug.cgi?id=11389
1123 alias TheType
= size_t
function( string
[] );
1124 static assert(arity
!TheType
== 1);
1128 Get tuple, one per function parameter, of the storage classes of the parameters.
1130 func = function symbol or type of function, delegate, or pointer to function
1132 A tuple of ParameterStorageClass bits
1134 enum ParameterStorageClass
: uint
1137 * These flags can be bitwise OR-ed together to represent complex storage
1141 in_
= 0x01, /// ditto
1142 ref_
= 0x02, /// ditto
1143 out_
= 0x04, /// ditto
1144 lazy_
= 0x08, /// ditto
1145 scope_
= 0x10, /// ditto
1146 return_
= 0x20, /// ditto
1150 template ParameterStorageClassTuple(alias func
)
1151 if (isCallable
!func
)
1153 alias Func
= FunctionTypeOf
!func
;
1155 static if (is(Func PT
== __parameters
))
1157 template StorageClass(size_t i
)
1159 static if (i
< PT
.length
)
1161 alias StorageClass
= AliasSeq
!(
1162 extractParameterStorageClassFlags
!(__traits(getParameterStorageClasses
, Func
, i
)),
1163 StorageClass
!(i
+ 1));
1166 alias StorageClass
= AliasSeq
!();
1168 alias ParameterStorageClassTuple
= StorageClass
!0;
1172 static assert(0, func
[0].stringof
~ " is not a function");
1173 alias ParameterStorageClassTuple
= AliasSeq
!();
1180 alias STC
= ParameterStorageClass
; // shorten the enum name
1182 void func(ref int ctx
, out real result
, in real param
, void* ptr
)
1185 alias pstc
= ParameterStorageClassTuple
!func
;
1186 static assert(pstc
.length
== 4); // number of parameters
1187 static assert(pstc
[0] == STC
.ref_
);
1188 static assert(pstc
[1] == STC
.out_
);
1191 // TODO: When the DMD PR (dlang/dmd#11474) gets merged,
1192 // remove the versioning and the second test
1193 static assert(pstc
[2] == STC
.in_
);
1194 // This is the current behavior, before `in` is fixed to not be an alias
1195 static assert(pstc
[2] == STC
.scope_
);
1197 static assert(pstc
[3] == STC
.none
);
1201 Convert the result of `__traits(getParameterStorageClasses)`
1202 to $(LREF ParameterStorageClass) `enum`s.
1205 Attribs = The return value of `__traits(getParameterStorageClasses)`
1207 The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s.
1209 template extractParameterStorageClassFlags(Attribs
...)
1211 enum ParameterStorageClass extractParameterStorageClassFlags
= ()
1213 auto result
= ParameterStorageClass
.none
;
1214 static if (Attribs
.length
> 0)
1216 static foreach (attrib
; Attribs
)
1218 final switch (attrib
) with (ParameterStorageClass
)
1220 case "scope": result |
= scope_
; break;
1221 case "in": result |
= in_
; break;
1222 case "out": result |
= out_
; break;
1223 case "ref": result |
= ref_
; break;
1224 case "lazy": result |
= lazy_
; break;
1225 case "return": result |
= return_
; break;
1228 /* Mimic behavor of original version of ParameterStorageClassTuple()
1229 * to avoid breaking existing code.
1231 if (result
== (ParameterStorageClass
.ref_ | ParameterStorageClass
.return_
))
1232 result
= ParameterStorageClass
.return_
;
1241 static void func(ref int ctx
, out real result
);
1243 enum param1
= extractParameterStorageClassFlags
!(
1244 __traits(getParameterStorageClasses
, func
, 0)
1246 static assert(param1
== ParameterStorageClass
.ref_
);
1248 enum param2
= extractParameterStorageClassFlags
!(
1249 __traits(getParameterStorageClasses
, func
, 1)
1251 static assert(param2
== ParameterStorageClass
.out_
);
1253 enum param3
= extractParameterStorageClassFlags
!(
1254 __traits(getParameterStorageClasses
, func
, 0),
1255 __traits(getParameterStorageClasses
, func
, 1)
1257 static assert(param3
== (ParameterStorageClass
.ref_ | ParameterStorageClass
.out_
));
1262 alias STC
= ParameterStorageClass
;
1265 static assert(ParameterStorageClassTuple
!noparam
.length
== 0);
1267 ref int test(scope int*, ref int, out int, lazy int, int, return ref int i
) { return i
; }
1268 alias test_pstc
= ParameterStorageClassTuple
!test;
1269 static assert(test_pstc
.length
== 6);
1270 static assert(test_pstc
[0] == STC
.scope_
);
1271 static assert(test_pstc
[1] == STC
.ref_
);
1272 static assert(test_pstc
[2] == STC
.out_
);
1273 static assert(test_pstc
[3] == STC
.lazy_
);
1274 static assert(test_pstc
[4] == STC
.none
);
1275 static assert(test_pstc
[5] == STC
.return_
);
1279 void test_const(int) const;
1280 void test_sharedconst(int) shared const;
1284 alias test_const_pstc
= ParameterStorageClassTuple
!(Test
.test_const
);
1285 static assert(test_const_pstc
.length
== 1);
1286 static assert(test_const_pstc
[0] == STC
.none
);
1288 alias test_sharedconst_pstc
= ParameterStorageClassTuple
!(testi
.test_sharedconst
);
1289 static assert(test_sharedconst_pstc
.length
== 1);
1290 static assert(test_sharedconst_pstc
[0] == STC
.none
);
1292 alias dglit_pstc
= ParameterStorageClassTuple
!((ref int a
) {});
1293 static assert(dglit_pstc
.length
== 1);
1294 static assert(dglit_pstc
[0] == STC
.ref_
);
1296 // https://issues.dlang.org/show_bug.cgi?id=9317
1297 static inout(int) func(inout int param
) { return param
; }
1298 static assert(ParameterStorageClassTuple
!(typeof(func
))[0] == STC
.none
);
1303 // https://issues.dlang.org/show_bug.cgi?id=14253
1305 ref Foo
opAssign(ref Foo rhs
) return { return this; }
1308 alias tup
= ParameterStorageClassTuple
!(__traits(getOverloads
, Foo
, "opAssign")[0]);
1313 Get, as a tuple, the identifiers of the parameters to a function symbol.
1315 template ParameterIdentifierTuple(alias func
)
1316 if (isCallable
!func
)
1318 static if (is(FunctionTypeOf
!func PT
== __parameters
))
1320 template Get(size_t i
)
1322 static if (!isFunctionPointer
!func
&& !isDelegate
!func
1323 // Unnamed parameters yield CT error.
1324 && is(typeof(__traits(identifier
, PT
[i
.. i
+1])))
1325 // Filter out unnamed args, which look like (Type) instead of (Type name).
1326 && PT
[i
].stringof
!= PT
[i
.. i
+1].stringof
[1..$-1])
1328 enum Get
= __traits(identifier
, PT
[i
.. i
+1]);
1338 static assert(0, func
.stringof
~ " is not a function");
1340 // Define dummy entities to avoid pointless errors
1341 template Get(size_t i
) { enum Get
= ""; }
1342 alias PT
= AliasSeq
!();
1345 template Impl(size_t i
= 0)
1347 static if (i
== PT
.length
)
1348 alias Impl
= AliasSeq
!();
1350 alias Impl
= AliasSeq
!(Get
!i
, Impl
!(i
+1));
1353 alias ParameterIdentifierTuple
= Impl
!();
1359 int foo(int num
, string name
, int);
1360 static assert([ParameterIdentifierTuple
!foo
] == ["num", "name", ""]);
1363 // https://issues.dlang.org/show_bug.cgi?id=19456
1369 static assert([ParameterIdentifierTuple
!foo
] == [""]);
1370 static assert([ParameterIdentifierTuple
!bar
] == [""]);
1375 alias PIT
= ParameterIdentifierTuple
;
1377 void bar(int num
, string name
, int[] array
){}
1378 static assert([PIT
!bar
] == ["num", "name", "array"]);
1380 // might be changed in the future?
1381 void function(int num
, string name
) fp
;
1382 static assert([PIT
!fp
] == ["", ""]);
1384 // might be changed in the future?
1385 void delegate(int num
, string name
, int[long] aa
) dg
;
1386 static assert([PIT
!dg
] == ["", "", ""]);
1390 @property string
getter();
1391 @property void setter(int a
);
1392 Test
method(int a
, long b
, string c
);
1394 static assert([PIT
!(Test
.getter
)] == []);
1395 static assert([PIT
!(Test
.setter
)] == ["a"]);
1396 static assert([PIT
!(Test
.method
)] == ["a", "b", "c"]);
1399 // depends on internal
1400 void baw(int, string, int[]){}
1401 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1403 // depends on internal
1404 void baz(AliasSeq!(int, string, int[]) args){}
1405 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1411 Get, as a tuple, the default value of the parameters to a function symbol.
1412 If a parameter doesn't have the default value, `void` is returned instead.
1414 template ParameterDefaults(alias func
)
1415 if (isCallable
!func
)
1417 alias param_names
= ParameterIdentifierTuple
!func
;
1418 static if (is(FunctionTypeOf
!(func
) PT
== __parameters
))
1420 template Get(size_t i
)
1422 // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1423 // To avoid a name clash, generate local names that are distinct
1424 // from the parameter name, and mix them in.
1425 enum name
= param_names
[i
];
1426 enum args
= "args" ~ (name
== "args" ?
"_" : "");
1427 enum val
= "val" ~ (name
== "val" ?
"_" : "");
1428 enum ptr
= "ptr" ~ (name
== "ptr" ?
"_" : "");
1430 enum hasDefaultArg = (PT[i .. i+1] " ~ args
~ ") { return true; };
1432 static if (is(typeof(hasDefaultArg())))
1435 // workaround scope escape check, see
1436 // https://issues.dlang.org/show_bug.cgi?id=16582
1437 // should use return scope once available
1438 enum get = (PT[i .. i+1] " ~ args
~ ") @trusted
1440 // If the parameter is lazy, we force it to be evaluated
1442 auto " ~ val
~ " = " ~ args
~ "[0];
1443 auto " ~ ptr
~ " = &" ~ val
~ ";
1444 return *" ~ ptr
~ ";
1450 // If default arg doesn't exist, returns void instead.
1455 static assert(0, func
.stringof
~ " is not a function");
1457 // Define dummy entities to avoid pointless errors
1458 template Get(size_t i
) { enum Get
= ""; }
1459 alias PT
= AliasSeq
!();
1462 template Impl(size_t i
= 0)
1464 static if (i
== PT
.length
)
1465 alias Impl
= AliasSeq
!();
1467 alias Impl
= AliasSeq
!(Get
!i
, Impl
!(i
+1));
1470 alias ParameterDefaults
= Impl
!();
1476 int foo(int num
, string name
= "hello", int[] = [1,2,3], lazy int x
= 0);
1477 static assert(is(ParameterDefaults
!foo
[0] == void));
1478 static assert( ParameterDefaults
!foo
[1] == "hello");
1479 static assert( ParameterDefaults
!foo
[2] == [1,2,3]);
1480 static assert( ParameterDefaults
!foo
[3] == 0);
1483 // https://issues.dlang.org/show_bug.cgi?id=17192
1486 static void func(int i
, int PT
, int __pd_value
, int __pd_val
, int __args
,
1487 int name
, int args
, int val
, int ptr
, int args_
, int val_
, int ptr_
)
1490 alias Voids
= ParameterDefaults
!func
;
1491 static assert(Voids
.length
== 12);
1492 static foreach (V
; Voids
) static assert(is(V
== void));
1495 // https://issues.dlang.org/show_bug.cgi?id=20182
1496 @safe pure nothrow @nogc unittest
1503 static assert(__traits(compiles
, ParameterDefaults
!(S
.__ctor
)));
1507 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1509 alias ParameterDefaultValueTuple
= ParameterDefaults
;
1513 alias PDVT
= ParameterDefaultValueTuple
;
1515 void bar(int n
= 1, string s
= "hello"){}
1516 static assert(PDVT
!bar
.length
== 2);
1517 static assert(PDVT
!bar
[0] == 1);
1518 static assert(PDVT
!bar
[1] == "hello");
1519 static assert(is(typeof(PDVT
!bar
) == typeof(AliasSeq
!(1, "hello"))));
1521 void baz(int x
, int n
= 1, string s
= "hello"){}
1522 static assert(PDVT
!baz
.length
== 3);
1523 static assert(is(PDVT
!baz
[0] == void));
1524 static assert( PDVT
!baz
[1] == 1);
1525 static assert( PDVT
!baz
[2] == "hello");
1526 static assert(is(typeof(PDVT
!baz
) == typeof(AliasSeq
!(void, 1, "hello"))));
1528 // property functions return empty string
1529 // https://issues.dlang.org/show_bug.cgi?id=10800
1530 @property void foo(int x
= 3) { }
1531 static assert(PDVT
!foo
.length
== 1);
1532 static assert(PDVT
!foo
[0] == 3);
1533 static assert(is(typeof(PDVT
!foo
) == typeof(AliasSeq
!(3))));
1539 static immutable Colour white
= Colour(255,255,255,255);
1541 // https://issues.dlang.org/show_bug.cgi?id=8106
1542 void bug8106(Colour c
= Colour
.white
) {}
1543 //pragma(msg, PDVT!bug8106);
1544 static assert(PDVT
!bug8106
[0] == Colour
.white
);
1545 // https://issues.dlang.org/show_bug.cgi?id=16582
1546 void bug16582(scope int* val
= null) {}
1547 static assert(PDVT
!bug16582
[0] is null);
1552 Returns the FunctionAttribute mask for function `func`.
1555 $(LREF hasFunctionAttributes)
1557 enum FunctionAttribute
: uint
1560 * These flags can be bitwise OR-ed together to represent a complex attribute.
1563 pure_
= 1 << 0, /// ditto
1564 nothrow_
= 1 << 1, /// ditto
1565 ref_
= 1 << 2, /// ditto
1566 property
= 1 << 3, /// ditto
1567 trusted
= 1 << 4, /// ditto
1568 safe
= 1 << 5, /// ditto
1569 nogc
= 1 << 6, /// ditto
1570 system
= 1 << 7, /// ditto
1571 const_
= 1 << 8, /// ditto
1572 immutable_
= 1 << 9, /// ditto
1573 inout_
= 1 << 10, /// ditto
1574 shared_
= 1 << 11, /// ditto
1575 return_
= 1 << 12, /// ditto
1576 scope_
= 1 << 13, /// ditto
1577 live
= 1 << 14, /// ditto
1581 template functionAttributes(alias func
)
1582 if (isCallable
!func
)
1584 // @bug: workaround for opCall
1585 alias FuncSym
= Select
!(is(typeof(__traits(getFunctionAttributes
, func
))),
1586 func
, Unqual
!(FunctionTypeOf
!func
));
1588 enum FunctionAttribute functionAttributes
=
1589 extractAttribFlags
!(__traits(getFunctionAttributes
, FuncSym
))();
1595 alias FA
= FunctionAttribute
; // shorten the enum name
1597 real func(real x
) pure nothrow @safe
1601 static assert(functionAttributes
!func
& FA
.pure_
);
1602 static assert(functionAttributes
!func
& FA
.safe
);
1603 static assert(!(functionAttributes
!func
& FA
.trusted
)); // not @trusted
1608 alias FA
= FunctionAttribute
;
1612 int noF() { return 0; }
1613 int constF() const { return 0; }
1614 int immutableF() immutable { return 0; }
1615 int inoutF() inout { return 0; }
1616 int sharedF() shared { return 0; }
1619 ref int refF() return { return x
; }
1620 int propertyF() @property { return 0; }
1621 int nothrowF() nothrow { return 0; }
1622 int nogcF() @nogc { return 0; }
1624 int systemF() @system { return 0; }
1625 int trustedF() @trusted { return 0; }
1626 int safeF() @safe { return 0; }
1628 int pureF() pure { return 0; }
1630 int liveF() @live { return 0; }
1633 static assert(functionAttributes
!(S
.noF
) == FA
.system
);
1634 static assert(functionAttributes
!(typeof(S
.noF
)) == FA
.system
);
1636 static assert(functionAttributes
!(S
.constF
) == (FA
.const_ | FA
.system
));
1637 static assert(functionAttributes
!(typeof(S
.constF
)) == (FA
.const_ | FA
.system
));
1639 static assert(functionAttributes
!(S
.immutableF
) == (FA
.immutable_ | FA
.system
));
1640 static assert(functionAttributes
!(typeof(S
.immutableF
)) == (FA
.immutable_ | FA
.system
));
1642 static assert(functionAttributes
!(S
.inoutF
) == (FA
.inout_ | FA
.system
));
1643 static assert(functionAttributes
!(typeof(S
.inoutF
)) == (FA
.inout_ | FA
.system
));
1645 static assert(functionAttributes
!(S
.sharedF
) == (FA
.shared_ | FA
.system
));
1646 static assert(functionAttributes
!(typeof(S
.sharedF
)) == (FA
.shared_ | FA
.system
));
1648 static assert(functionAttributes
!(S
.refF
) == (FA
.ref_ | FA
.system | FA
.return_
));
1649 static assert(functionAttributes
!(typeof(S
.refF
)) == (FA
.ref_ | FA
.system | FA
.return_
));
1651 static assert(functionAttributes
!(S
.propertyF
) == (FA
.property | FA
.system
));
1652 static assert(functionAttributes
!(typeof(&S
.propertyF
)) == (FA
.property | FA
.system
));
1654 static assert(functionAttributes
!(S
.nothrowF
) == (FA
.nothrow_ | FA
.system
));
1655 static assert(functionAttributes
!(typeof(S
.nothrowF
)) == (FA
.nothrow_ | FA
.system
));
1657 static assert(functionAttributes
!(S
.nogcF
) == (FA
.nogc | FA
.system
));
1658 static assert(functionAttributes
!(typeof(S
.nogcF
)) == (FA
.nogc | FA
.system
));
1660 static assert(functionAttributes
!(S
.systemF
) == FA
.system
);
1661 static assert(functionAttributes
!(typeof(S
.systemF
)) == FA
.system
);
1663 static assert(functionAttributes
!(S
.trustedF
) == FA
.trusted
);
1664 static assert(functionAttributes
!(typeof(S
.trustedF
)) == FA
.trusted
);
1666 static assert(functionAttributes
!(S
.safeF
) == FA
.safe
);
1667 static assert(functionAttributes
!(typeof(S
.safeF
)) == FA
.safe
);
1669 static assert(functionAttributes
!(S
.pureF
) == (FA
.pure_ | FA
.system
));
1670 static assert(functionAttributes
!(typeof(S
.pureF
)) == (FA
.pure_ | FA
.system
));
1672 static assert(functionAttributes
!(S
.liveF
) == (FA
.live | FA
.system
));
1673 static assert(functionAttributes
!(typeof(S
.liveF
)) == (FA
.live | FA
.system
));
1675 int pure_nothrow() nothrow pure;
1676 void safe_nothrow() @safe nothrow;
1677 static ref int static_ref_property() @property;
1678 ref int ref_property() @property;
1680 static assert(functionAttributes
!(pure_nothrow
) == (FA
.pure_ | FA
.nothrow_ | FA
.system
));
1681 static assert(functionAttributes
!(typeof(pure_nothrow
)) == (FA
.pure_ | FA
.nothrow_ | FA
.system
));
1683 static assert(functionAttributes
!(safe_nothrow
) == (FA
.safe | FA
.nothrow_
));
1684 static assert(functionAttributes
!(typeof(safe_nothrow
)) == (FA
.safe | FA
.nothrow_
));
1686 static assert(functionAttributes
!(static_ref_property
) == (FA
.property | FA
.ref_ | FA
.system
));
1687 static assert(functionAttributes
!(typeof(&static_ref_property
)) == (FA
.property | FA
.ref_ | FA
.system
));
1689 static assert(functionAttributes
!(ref_property
) == (FA
.property | FA
.ref_ | FA
.system
));
1690 static assert(functionAttributes
!(typeof(&ref_property
)) == (FA
.property | FA
.ref_ | FA
.system
));
1694 int pure_const() const pure { return 0; }
1695 int pure_sharedconst() const shared pure { return 0; }
1698 static assert(functionAttributes
!(S2
.pure_const
) == (FA
.const_ | FA
.pure_ | FA
.system
));
1699 static assert(functionAttributes
!(typeof(S2
.pure_const
)) == (FA
.const_ | FA
.pure_ | FA
.system
));
1701 static assert(functionAttributes
!(S2
.pure_sharedconst
) == (FA
.const_ | FA
.shared_ | FA
.pure_ | FA
.system
));
1702 static assert(functionAttributes
!(typeof(S2
.pure_sharedconst
)) == (FA
.const_ | FA
.shared_ | FA
.pure_ | FA
.system
));
1704 static assert(functionAttributes
!((int a
) { }) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.safe
));
1705 static assert(functionAttributes
!(typeof((int a
) { })) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.safe
));
1707 auto safeDel
= delegate() @safe { };
1708 static assert(functionAttributes
!(safeDel
) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.safe
));
1709 static assert(functionAttributes
!(typeof(safeDel
)) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.safe
));
1711 auto trustedDel
= delegate() @trusted { };
1712 static assert(functionAttributes
!(trustedDel
) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.trusted
));
1713 static assert(functionAttributes
!(typeof(trustedDel
)) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.trusted
));
1715 auto systemDel
= delegate() @system { };
1716 static assert(functionAttributes
!(systemDel
) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.system
));
1717 static assert(functionAttributes
!(typeof(systemDel
)) == (FA
.pure_ | FA
.nothrow_ | FA
.nogc | FA
.system
));
1720 private FunctionAttribute
extractAttribFlags(Attribs
...)()
1722 auto res
= FunctionAttribute
.none
;
1724 static foreach (attrib
; Attribs
)
1726 switch (attrib
) with (FunctionAttribute
)
1728 case "pure": res |
= pure_
; break;
1729 case "nothrow": res |
= nothrow_
; break;
1730 case "ref": res |
= ref_
; break;
1731 case "@property": res |
= property
; break;
1732 case "@trusted": res |
= trusted
; break;
1733 case "@safe": res |
= safe
; break;
1734 case "@nogc": res |
= nogc
; break;
1735 case "@system": res |
= system
; break;
1736 case "const": res |
= const_
; break;
1737 case "immutable": res |
= immutable_
; break;
1738 case "inout": res |
= inout_
; break;
1739 case "shared": res |
= shared_
; break;
1740 case "return": res |
= return_
; break;
1741 case "scope": res |
= scope_
; break;
1742 case "@live": res |
= live
; break;
1743 default: assert(0, attrib
);
1751 Checks whether a function has the given attributes attached.
1754 args = Function to check, followed by a
1755 variadic number of function attributes as strings
1758 `true`, if the function has the list of attributes attached and `false` otherwise.
1761 $(LREF functionAttributes)
1763 template hasFunctionAttributes(args
...)
1764 if (args
.length
> 0 && isCallable
!(args
[0])
1765 && allSatisfy
!(isSomeString
, typeof(args
[1 .. $])))
1767 enum bool hasFunctionAttributes
= {
1768 import std
.algorithm
.searching
: canFind
;
1769 import std
.range
: only
;
1770 enum funcAttribs
= only(__traits(getFunctionAttributes
, args
[0]));
1771 static foreach (attribute
; args
[1 .. $])
1773 if (!funcAttribs
.canFind(attribute
))
1783 real func(real x
) pure nothrow @safe;
1784 static assert(hasFunctionAttributes
!(func
, "@safe", "pure"));
1785 static assert(!hasFunctionAttributes
!(func
, "@trusted"));
1787 // for templates attributes are automatically inferred
1792 static assert(hasFunctionAttributes
!(myFunc
!bool, "@safe", "pure", "@nogc", "nothrow"));
1793 static assert(!hasFunctionAttributes
!(myFunc
!bool, "shared"));
1802 int immutableF() immutable;
1804 int sharedF() shared;
1806 ref int refF() return;
1807 int propertyF() @property;
1808 int nothrowF() nothrow;
1811 int systemF() @system;
1812 int trustedF() @trusted;
1820 // true if no args passed
1821 static assert(hasFunctionAttributes
!(S
.noF
));
1823 static assert(hasFunctionAttributes
!(S
.noF
, "@system"));
1824 static assert(hasFunctionAttributes
!(typeof(S
.noF
), "@system"));
1825 static assert(!hasFunctionAttributes
!(S
.noF
, "@system", "pure"));
1827 static assert(hasFunctionAttributes
!(S
.constF
, "const", "@system"));
1828 static assert(hasFunctionAttributes
!(typeof(S
.constF
), "const", "@system"));
1829 static assert(!hasFunctionAttributes
!(S
.constF
, "const", "@system", "@nogc"));
1831 static assert(hasFunctionAttributes
!(S
.immutableF
, "immutable", "@system"));
1832 static assert(hasFunctionAttributes
!(typeof(S
.immutableF
), "immutable", "@system"));
1833 static assert(!hasFunctionAttributes
!(S
.immutableF
, "immutable", "@system", "pure"));
1835 static assert(hasFunctionAttributes
!(S
.inoutF
, "inout", "@system"));
1836 static assert(hasFunctionAttributes
!(typeof(S
.inoutF
), "inout", "@system"));
1837 static assert(!hasFunctionAttributes
!(S
.inoutF
, "inout", "@system", "pure"));
1839 static assert(hasFunctionAttributes
!(S
.sharedF
, "shared", "@system"));
1840 static assert(hasFunctionAttributes
!(typeof(S
.sharedF
), "shared", "@system"));
1841 static assert(!hasFunctionAttributes
!(S
.sharedF
, "shared", "@system", "@trusted"));
1843 static assert(hasFunctionAttributes
!(S
.refF
, "ref", "@system", "return"));
1844 static assert(hasFunctionAttributes
!(typeof(S
.refF
), "ref", "@system", "return"));
1845 static assert(!hasFunctionAttributes
!(S
.refF
, "ref", "@system", "return", "pure"));
1847 static assert(hasFunctionAttributes
!(S
.propertyF
, "@property", "@system"));
1848 static assert(hasFunctionAttributes
!(typeof(&S
.propertyF
), "@property", "@system"));
1849 static assert(!hasFunctionAttributes
!(S
.propertyF
, "@property", "@system", "ref"));
1851 static assert(hasFunctionAttributes
!(S
.nothrowF
, "nothrow", "@system"));
1852 static assert(hasFunctionAttributes
!(typeof(S
.nothrowF
), "nothrow", "@system"));
1853 static assert(!hasFunctionAttributes
!(S
.nothrowF
, "nothrow", "@system", "@trusted"));
1855 static assert(hasFunctionAttributes
!(S
.nogcF
, "@nogc", "@system"));
1856 static assert(hasFunctionAttributes
!(typeof(S
.nogcF
), "@nogc", "@system"));
1857 static assert(!hasFunctionAttributes
!(S
.nogcF
, "@nogc", "@system", "ref"));
1859 static assert(hasFunctionAttributes
!(S
.systemF
, "@system"));
1860 static assert(hasFunctionAttributes
!(typeof(S
.systemF
), "@system"));
1861 static assert(!hasFunctionAttributes
!(S
.systemF
, "@system", "ref"));
1863 static assert(hasFunctionAttributes
!(S
.trustedF
, "@trusted"));
1864 static assert(hasFunctionAttributes
!(typeof(S
.trustedF
), "@trusted"));
1865 static assert(!hasFunctionAttributes
!(S
.trustedF
, "@trusted", "@safe"));
1867 static assert(hasFunctionAttributes
!(S
.safeF
, "@safe"));
1868 static assert(hasFunctionAttributes
!(typeof(S
.safeF
), "@safe"));
1869 static assert(!hasFunctionAttributes
!(S
.safeF
, "@safe", "nothrow"));
1871 static assert(hasFunctionAttributes
!(S
.pureF
, "pure", "@system"));
1872 static assert(hasFunctionAttributes
!(typeof(S
.pureF
), "pure", "@system"));
1873 static assert(!hasFunctionAttributes
!(S
.pureF
, "pure", "@system", "ref"));
1875 static assert(hasFunctionAttributes
!(S
.liveF
, "@live", "@system"));
1876 static assert(hasFunctionAttributes
!(typeof(S
.liveF
), "@live", "@system"));
1877 static assert(!hasFunctionAttributes
!(S
.liveF
, "@live", "@system", "ref"));
1879 int pure_nothrow() nothrow pure { return 0; }
1880 void safe_nothrow() @safe nothrow { }
1881 static ref int static_ref_property() @property { return *(new int); }
1882 ref int ref_property() @property { return *(new int); }
1884 static assert(hasFunctionAttributes
!(pure_nothrow
, "pure", "nothrow", "@safe"));
1885 static assert(hasFunctionAttributes
!(typeof(pure_nothrow
), "pure", "nothrow", "@safe"));
1886 static assert(!hasFunctionAttributes
!(pure_nothrow
, "pure", "nothrow", "@safe", "@trusted"));
1888 static assert(hasFunctionAttributes
!(safe_nothrow
, "@safe", "nothrow"));
1889 static assert(hasFunctionAttributes
!(typeof(safe_nothrow
), "@safe", "nothrow"));
1890 static assert(hasFunctionAttributes
!(safe_nothrow
, "@safe", "nothrow", "pure"));
1891 static assert(!hasFunctionAttributes
!(safe_nothrow
, "@safe", "nothrow", "pure", "@trusted"));
1893 static assert(hasFunctionAttributes
!(static_ref_property
, "@property", "ref", "@safe"));
1894 static assert(hasFunctionAttributes
!(typeof(&static_ref_property
), "@property", "ref", "@safe"));
1895 static assert(hasFunctionAttributes
!(static_ref_property
, "@property", "ref", "@safe", "nothrow"));
1896 static assert(!hasFunctionAttributes
!(static_ref_property
, "@property", "ref", "@safe", "nothrow", "@nogc"));
1898 static assert(hasFunctionAttributes
!(ref_property
, "@property", "ref", "@safe"));
1899 static assert(hasFunctionAttributes
!(typeof(&ref_property
), "@property", "ref", "@safe"));
1900 static assert(!hasFunctionAttributes
!(ref_property
, "@property", "ref", "@safe", "@nogc"));
1904 int pure_const() const pure { return 0; }
1905 int pure_sharedconst() const shared pure { return 0; }
1908 static assert(hasFunctionAttributes
!(S2
.pure_const
, "const", "pure", "@system"));
1909 static assert(hasFunctionAttributes
!(typeof(S2
.pure_const
), "const", "pure", "@system"));
1910 static assert(!hasFunctionAttributes
!(S2
.pure_const
, "const", "pure", "@system", "ref"));
1912 static assert(hasFunctionAttributes
!(S2
.pure_sharedconst
, "const", "shared", "pure", "@system"));
1913 static assert(hasFunctionAttributes
!(typeof(S2
.pure_sharedconst
), "const", "shared", "pure", "@system"));
1914 static assert(!hasFunctionAttributes
!(S2
.pure_sharedconst
, "const", "shared", "pure", "@system", "@nogc"));
1916 static assert(hasFunctionAttributes
!((int a
) { }, "pure", "nothrow", "@nogc", "@safe"));
1917 static assert(hasFunctionAttributes
!(typeof((int a
) { }), "pure", "nothrow", "@nogc", "@safe"));
1918 static assert(!hasFunctionAttributes
!((int a
) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1920 auto safeDel
= delegate() @safe { };
1921 static assert(hasFunctionAttributes
!(safeDel
, "pure", "nothrow", "@nogc", "@safe"));
1922 static assert(hasFunctionAttributes
!(typeof(safeDel
), "pure", "nothrow", "@nogc", "@safe"));
1923 static assert(!hasFunctionAttributes
!(safeDel
, "pure", "nothrow", "@nogc", "@safe", "@system"));
1925 auto trustedDel
= delegate() @trusted { };
1926 static assert(hasFunctionAttributes
!(trustedDel
, "pure", "nothrow", "@nogc", "@trusted"));
1927 static assert(hasFunctionAttributes
!(typeof(trustedDel
), "pure", "nothrow", "@nogc", "@trusted"));
1928 static assert(!hasFunctionAttributes
!(trustedDel
, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1930 auto systemDel
= delegate() @system { };
1931 static assert(hasFunctionAttributes
!(systemDel
, "pure", "nothrow", "@nogc", "@system"));
1932 static assert(hasFunctionAttributes
!(typeof(systemDel
), "pure", "nothrow", "@nogc", "@system"));
1933 static assert(!hasFunctionAttributes
!(systemDel
, "pure", "nothrow", "@nogc", "@system", "@property"));
1936 // call functions to make CodeCov happy
1938 assert(pure_nothrow
== 0);
1940 assert(static_ref_property
== 0);
1941 assert(ref_property
== 0);
1942 assert(S2().pure_const
== 0);
1943 assert((shared S2()).pure_sharedconst
== 0);
1945 cast(void) trustedDel
;
1946 cast(void) systemDel
;
1951 `true` if `func` is `@safe` or `@trusted`.
1953 template isSafe(alias func
)
1954 if (isCallable
!func
)
1956 enum isSafe
= (functionAttributes
!func
& FunctionAttribute
.safe
) != 0 ||
1957 (functionAttributes
!func
& FunctionAttribute
.trusted
) != 0;
1963 @safe int add(int a
, int b
) {return a
+b
;}
1964 @trusted int sub(int a
, int b
) {return a
-b
;}
1965 @system int mul(int a
, int b
) {return a
*b
;}
1967 static assert( isSafe
!add);
1968 static assert( isSafe
!sub);
1969 static assert(!isSafe
!mul);
1978 int systemF() @system;
1979 int trustedF() @trusted;
1982 static assert( isSafe
!(Set
.safeF
));
1983 static assert( isSafe
!(Set
.trustedF
));
1984 static assert(!isSafe
!(Set
.systemF
));
1987 @safe static void safeFunc() {}
1988 @trusted static void trustedFunc() {}
1989 @system static void systemFunc() {}
1991 static assert( isSafe
!safeFunc
);
1992 static assert( isSafe
!trustedFunc
);
1993 static assert(!isSafe
!systemFunc
);
1996 auto safeDel
= delegate() @safe {};
1997 auto trustedDel
= delegate() @trusted {};
1998 auto systemDel
= delegate() @system {};
2000 static assert( isSafe
!safeDel
);
2001 static assert( isSafe
!trustedDel
);
2002 static assert(!isSafe
!systemDel
);
2005 static assert( isSafe
!({safeDel();}));
2006 static assert( isSafe
!({trustedDel();}));
2007 static assert(!isSafe
!({systemDel();}));
2010 struct SafeStatic
{ @safe static SafeStatic
opCall() { return SafeStatic
.init
; } }
2011 struct TrustedStatic
{ @trusted static TrustedStatic
opCall() { return TrustedStatic
.init
; } }
2012 struct SystemStatic
{ @system static SystemStatic
opCall() { return SystemStatic
.init
; } }
2014 static assert( isSafe
!(SafeStatic()));
2015 static assert( isSafe
!(TrustedStatic()));
2016 static assert(!isSafe
!(SystemStatic()));
2019 struct Safe
{ @safe Safe
opCall() { return Safe
.init
; } }
2020 struct Trusted
{ @trusted Trusted
opCall() { return Trusted
.init
; } }
2021 struct System
{ @system System
opCall() { return System
.init
; } }
2023 static assert( isSafe
!(Safe
.init()));
2024 static assert( isSafe
!(Trusted
.init()));
2025 static assert(!isSafe
!(System
.init()));
2030 `true` if `func` is `@system`.
2032 template isUnsafe(alias func
)
2034 enum isUnsafe
= !isSafe
!func
;
2040 @safe int add(int a
, int b
) {return a
+b
;}
2041 @trusted int sub(int a
, int b
) {return a
-b
;}
2042 @system int mul(int a
, int b
) {return a
*b
;}
2044 static assert(!isUnsafe
!add);
2045 static assert(!isUnsafe
!sub);
2046 static assert( isUnsafe
!mul);
2054 int systemF() @system;
2055 int trustedF() @trusted;
2058 static assert(!isUnsafe
!(Set
.safeF
));
2059 static assert(!isUnsafe
!(Set
.trustedF
));
2060 static assert( isUnsafe
!(Set
.systemF
));
2063 @safe static void safeFunc() {}
2064 @trusted static void trustedFunc() {}
2065 @system static void systemFunc() {}
2067 static assert(!isUnsafe
!safeFunc
);
2068 static assert(!isUnsafe
!trustedFunc
);
2069 static assert( isUnsafe
!systemFunc
);
2072 auto safeDel
= delegate() @safe {};
2073 auto trustedDel
= delegate() @trusted {};
2074 auto systemDel
= delegate() @system {};
2076 static assert(!isUnsafe
!safeDel
);
2077 static assert(!isUnsafe
!trustedDel
);
2078 static assert( isUnsafe
!systemDel
);
2081 static assert(!isUnsafe
!({safeDel();}));
2082 static assert(!isUnsafe
!({trustedDel();}));
2083 static assert( isUnsafe
!({systemDel();}));
2086 struct SafeStatic
{ @safe static SafeStatic
opCall() { return SafeStatic
.init
; } }
2087 struct TrustedStatic
{ @trusted static TrustedStatic
opCall() { return TrustedStatic
.init
; } }
2088 struct SystemStatic
{ @system static SystemStatic
opCall() { return SystemStatic
.init
; } }
2090 static assert(!isUnsafe
!(SafeStatic()));
2091 static assert(!isUnsafe
!(TrustedStatic()));
2092 static assert( isUnsafe
!(SystemStatic()));
2095 struct Safe
{ @safe Safe
opCall() { return Safe
.init
; } }
2096 struct Trusted
{ @trusted Trusted
opCall() { return Trusted
.init
; } }
2097 struct System
{ @system System
opCall() { return System
.init
; } }
2099 static assert(!isUnsafe
!(Safe
.init()));
2100 static assert(!isUnsafe
!(Trusted
.init()));
2101 static assert( isUnsafe
!(System
.init()));
2106 Determine the linkage attribute of the function.
2108 func = the function symbol, or the type of a function, delegate, or pointer to function
2110 one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
2112 template functionLinkage(alias func
)
2113 if (isCallable
!func
)
2115 enum string functionLinkage
= __traits(getLinkage
, FunctionTypeOf
!func
);
2121 extern(D
) void Dfunc() {}
2122 extern(C
) void Cfunc() {}
2123 static assert(functionLinkage
!Dfunc
== "D");
2124 static assert(functionLinkage
!Cfunc
== "C");
2126 string a
= functionLinkage
!Dfunc
;
2130 string b
= functionLinkage
!fp
;
2138 void const_func() const;
2139 void sharedconst_func() shared const;
2141 static assert(functionLinkage
!(Test
.const_func
) == "D");
2142 static assert(functionLinkage
!(Test
.sharedconst_func
) == "D");
2144 static assert(functionLinkage
!((int a
){}) == "D");
2149 Determines what kind of variadic parameters function has.
2151 func = function symbol or type of function, delegate, or pointer to function
2157 /// Function is not variadic.
2159 /// Function is a _C-style variadic function, which uses
2160 /// `core.stdc.stdarg`
2162 /// Function is a _D-style variadic function, which uses
2163 /// `__argptr` and `__arguments`.
2165 /// Function is a typesafe variadic function.
2170 template variadicFunctionStyle(alias func
)
2171 if (isCallable
!func
)
2173 enum string varargs
= __traits(getFunctionVariadicStyle
, FunctionTypeOf
!func
);
2174 enum Variadic variadicFunctionStyle
=
2175 (varargs
== "stdarg") ? Variadic
.c
:
2176 (varargs
== "argptr") ? Variadic
.d
:
2177 (varargs
== "typesafe") ? Variadic
.typesafe
:
2178 (varargs
== "none") ? Variadic
.no
: Variadic
.no
;
2185 static assert(variadicFunctionStyle
!func
== Variadic
.no
);
2187 extern(C
) int printf(in char*, ...);
2188 static assert(variadicFunctionStyle
!printf
== Variadic
.c
);
2195 extern(D
) void novar() {}
2196 extern(C
) void cstyle(int, ...) {}
2197 extern(D
) void dstyle(...) {}
2198 extern(D
) void typesafe(int[]...) {}
2200 static assert(variadicFunctionStyle
!novar
== Variadic
.no
);
2201 static assert(variadicFunctionStyle
!cstyle
== Variadic
.c
);
2202 static assert(variadicFunctionStyle
!dstyle
== Variadic
.d
);
2203 static assert(variadicFunctionStyle
!typesafe
== Variadic
.typesafe
);
2205 static assert(variadicFunctionStyle
!((int[] a
...) {}) == Variadic
.typesafe
);
2210 Get the function type from a callable object `func`.
2212 Using builtin `typeof` on a property function yields the types of the
2213 property value, not of the property function itself. Still,
2214 `FunctionTypeOf` is able to obtain function types of properties.
2217 Do not confuse function types with function pointer types; function types are
2218 usually used for compile-time reflection purposes.
2220 template FunctionTypeOf(alias func
)
2221 if (isCallable
!func
)
2223 static if ((is(typeof(& func
) Fsym
: Fsym
*) && is(Fsym
== function)) ||
is(typeof(& func
) Fsym
== delegate))
2225 alias FunctionTypeOf
= Fsym
; // HIT: (nested) function symbol
2227 else static if (is(typeof(& func
.opCall
) Fobj
== delegate) ||
is(typeof(& func
.opCall
!()) Fobj
== delegate))
2229 alias FunctionTypeOf
= Fobj
; // HIT: callable object
2232 (is(typeof(& func
.opCall
) Ftyp
: Ftyp
*) && is(Ftyp
== function)) ||
2233 (is(typeof(& func
.opCall
!()) Ftyp
: Ftyp
*) && is(Ftyp
== function))
2236 alias FunctionTypeOf
= Ftyp
; // HIT: callable type
2238 else static if (is(func T
) ||
is(typeof(func
) T
))
2240 static if (is(T
== function))
2241 alias FunctionTypeOf
= T
; // HIT: function
2242 else static if (is(T Fptr
: Fptr
*) && is(Fptr
== function))
2243 alias FunctionTypeOf
= Fptr
; // HIT: function pointer
2244 else static if (is(T Fdlg
== delegate))
2245 alias FunctionTypeOf
= Fdlg
; // HIT: delegate
2258 int value() @property { return 0; }
2260 static assert(is( typeof(C
.value
) == int ));
2261 static assert(is( FunctionTypeOf
!(C
.value
) == function ));
2267 int propGet() @property;
2268 int propSet(int a
) @property;
2269 int function(int) test_fp
;
2270 int delegate(int) test_dg
;
2271 static assert(is( typeof(test) == FunctionTypeOf
!(typeof(test)) ));
2272 static assert(is( typeof(test) == FunctionTypeOf
!test ));
2273 static assert(is( typeof(test) == FunctionTypeOf
!test_fp
));
2274 static assert(is( typeof(test) == FunctionTypeOf
!test_dg
));
2275 alias int GetterType() @property;
2276 alias int SetterType(int) @property;
2277 static assert(is( FunctionTypeOf
!propGet
== GetterType
));
2278 static assert(is( FunctionTypeOf
!propSet
== SetterType
));
2280 interface Prop
{ int prop() @property; }
2282 static assert(is( FunctionTypeOf
!(Prop
.prop
) == GetterType
));
2283 static assert(is( FunctionTypeOf
!(prop
.prop
) == GetterType
));
2285 class Callable
{ int opCall(int) { return 0; } }
2286 auto call = new Callable
;
2287 static assert(is( FunctionTypeOf
!call == typeof(test) ));
2289 struct StaticCallable
{ static int opCall(int) { return 0; } }
2290 StaticCallable stcall_val
;
2291 StaticCallable
* stcall_ptr
;
2292 static assert(is( FunctionTypeOf
!stcall_val
== typeof(test) ));
2293 static assert(is( FunctionTypeOf
!stcall_ptr
== typeof(test) ));
2295 struct TemplatedOpCallF
{ int opCall()(int) { return 0; } }
2296 static assert(is( FunctionTypeOf
!TemplatedOpCallF
== typeof(TemplatedOpCallF
.opCall
!()) ));
2299 struct TemplatedOpCallDg
{ int opCall()() { return foovar
; } }
2300 static assert(is( FunctionTypeOf
!TemplatedOpCallDg
== typeof(TemplatedOpCallDg
.opCall
!()) ));
2307 int test() @property;
2309 alias ov
= __traits(getVirtualMethods
, Overloads
, "test");
2310 alias F_ov0
= FunctionTypeOf
!(ov
[0]);
2311 alias F_ov1
= FunctionTypeOf
!(ov
[1]);
2312 alias F_ov2
= FunctionTypeOf
!(ov
[2]);
2313 alias F_ov3
= FunctionTypeOf
!(ov
[3]);
2314 static assert(is(F_ov0
* == void function(string
)));
2315 static assert(is(F_ov1
* == real function(real)));
2316 static assert(is(F_ov2
* == int function(int)));
2317 static assert(is(F_ov3
* == int function() @property));
2319 alias F_dglit
= FunctionTypeOf
!((int a
){ return a
; });
2320 static assert(is(F_dglit
* : int function(int)));
2324 * Constructs a new function or delegate type with the same basic signature
2325 * as the given one, but different attributes (including linkage).
2327 * This is especially useful for adding/removing attributes to/from types in
2328 * generic code, where the actual type name cannot be spelt out.
2331 * T = The base type.
2332 * linkage = The desired linkage of the result type.
2333 * attrs = The desired $(LREF FunctionAttribute)s of the result type.
2335 template SetFunctionAttributes(T
, string linkage
, uint attrs
)
2336 if (isFunctionPointer
!T || isDelegate
!T
)
2339 import std
.algorithm
.searching
: canFind
;
2341 static assert(!(attrs
& FunctionAttribute
.trusted
) ||
2342 !(attrs
& FunctionAttribute
.safe
),
2343 "Cannot have a function/delegate that is both trusted and safe.");
2345 static immutable linkages
= ["D", "C", "Windows", "C++", "System"];
2346 static assert(canFind(linkages
, linkage
), "Invalid linkage '" ~
2347 linkage
~ "', must be one of " ~ linkages
.stringof
~ ".");
2349 string result
= "alias ";
2351 static if (linkage
!= "D")
2352 result
~= "extern(" ~ linkage
~ ") ";
2354 static if (attrs
& FunctionAttribute
.ref_
)
2357 result
~= "ReturnType!T";
2359 static if (isDelegate
!T
)
2360 result
~= " delegate";
2362 result
~= " function";
2366 static if (Parameters
!T
.length
> 0)
2367 result
~= "Parameters!T";
2369 enum varStyle
= variadicFunctionStyle
!T
;
2370 static if (varStyle
== Variadic
.c
)
2372 else static if (varStyle
== Variadic
.d
)
2374 else static if (varStyle
== Variadic
.typesafe
)
2379 static if (attrs
& FunctionAttribute
.pure_
)
2381 static if (attrs
& FunctionAttribute
.nothrow_
)
2382 result
~= " nothrow";
2383 static if (attrs
& FunctionAttribute
.property
)
2384 result
~= " @property";
2385 static if (attrs
& FunctionAttribute
.trusted
)
2386 result
~= " @trusted";
2387 static if (attrs
& FunctionAttribute
.safe
)
2389 static if (attrs
& FunctionAttribute
.nogc
)
2391 static if (attrs
& FunctionAttribute
.system
)
2392 result
~= " @system";
2393 static if (attrs
& FunctionAttribute
.const_
)
2395 static if (attrs
& FunctionAttribute
.immutable_
)
2396 result
~= " immutable";
2397 static if (attrs
& FunctionAttribute
.inout_
)
2399 static if (attrs
& FunctionAttribute
.shared_
)
2400 result
~= " shared";
2401 static if (attrs
& FunctionAttribute
.return_
)
2402 result
~= " return";
2403 static if (attrs
& FunctionAttribute
.live
)
2406 result
~= " SetFunctionAttributes;";
2412 template SetFunctionAttributes(T
, string linkage
, uint attrs
)
2413 if (is(T
== function))
2415 // To avoid a lot of syntactic headaches, we just use the above version to
2416 // operate on the corresponding function pointer type and then remove the
2417 // indirection again.
2418 alias SetFunctionAttributes
= FunctionTypeOf
!(SetFunctionAttributes
!(T
*, linkage
, attrs
));
2424 alias ExternC(T
) = SetFunctionAttributes
!(T
, "C", functionAttributes
!T
);
2426 auto assumePure(T
)(T t
)
2427 if (isFunctionPointer
!T || isDelegate
!T
)
2429 enum attrs
= functionAttributes
!T | FunctionAttribute
.pure_
;
2430 return cast(SetFunctionAttributes
!(T
, functionLinkage
!T
, attrs
)) t
;
2435 import core
.thread
: getpid
;
2439 int g() pure @trusted
2441 auto pureF
= assumePure(&f
);
2447 version (StdUnittest
)
2450 // Some function types to test.
2451 int sc(scope int, ref int, out int, lazy int, int);
2452 extern(System
) int novar();
2453 extern(C
) int cstyle(int, ...);
2454 extern(D
) int dstyle(...);
2455 extern(D
) int typesafe(int[]...);
2459 import std
.algorithm
.iteration
: reduce
;
2461 alias FA
= FunctionAttribute
;
2462 static foreach (BaseT
; AliasSeq
!(typeof(&sc
), typeof(&novar
), typeof(&cstyle
),
2463 typeof(&dstyle
), typeof(&typesafe
)))
2465 static foreach (T
; AliasSeq
!(BaseT
, FunctionTypeOf
!BaseT
))
2467 enum linkage
= functionLinkage
!T
;
2468 enum attrs
= functionAttributes
!T
;
2470 static assert(is(SetFunctionAttributes
!(T
, linkage
, attrs
) == T
),
2471 "Identity check failed for: " ~ T
.stringof
);
2473 // Check that all linkage types work (D-style variadics require D linkage).
2474 static if (variadicFunctionStyle
!T
!= Variadic
.d
)
2476 static foreach (newLinkage
; AliasSeq
!("D", "C", "Windows", "C++"))
2478 alias New
= SetFunctionAttributes
!(T
, newLinkage
, attrs
);
2479 static assert(functionLinkage
!New
== newLinkage
,
2480 "Linkage test failed for: " ~ T
.stringof
~ ", " ~ newLinkage
~
2481 " (got " ~ New
.stringof
~ ")");
2486 alias T1
= SetFunctionAttributes
!(T
, functionLinkage
!T
, FA
.safe
);
2487 static assert(functionAttributes
!T1
== FA
.safe
);
2489 // Add all known attributes, excluding conflicting ones.
2490 enum allAttrs
= reduce
!"a | b"([EnumMembers
!FA
])
2491 & ~FA
.safe
& ~FA
.property
& ~FA
.const_
& ~FA
.immutable_
& ~FA
.inout_
2492 & ~FA
.shared_
& ~FA
.system
& ~FA
.return_
& ~FA
.scope_
;
2494 alias T2
= SetFunctionAttributes
!(T1
, functionLinkage
!T
, allAttrs
);
2495 static assert(functionAttributes
!T2
== allAttrs
);
2497 // Strip all attributes again.
2498 alias T3
= SetFunctionAttributes
!(T2
, functionLinkage
!T
, FA
.none
);
2499 static assert(is(T3
== T
));
2505 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2507 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
2510 Determines whether `T` is a class nested inside another class
2511 and that `T.outer` is the implicit reference to the outer class
2512 (i.e. `outer` has not been used as a field or method name)
2518 `true` if `T` is a class nested inside another, with the conditions described above;
2521 template isInnerClass(T
)
2524 static if (is(typeof(T
.outer
)))
2526 bool hasOuterMember(string
[] members
...)
2528 foreach (m
; members
)
2535 enum isInnerClass
= __traits(isSame
, typeof(T
.outer
), __traits(parent
, T
)) &&
2536 !hasOuterMember(__traits(allMembers
, T
));
2539 enum isInnerClass
= false;
2549 static assert(!isInnerClass
!C
);
2559 static assert(isInnerClass
!(Outer1
.Inner1
));
2560 static assert(!isInnerClass
!(Outer1
.Inner2
));
2569 static assert(!isInnerClass
!(Outer2
.Inner
));
2573 Determines whether `T` has its own context pointer.
2574 `T` must be either `class`, `struct`, or `union`.
2576 template isNested(T
)
2577 if (is(T
== class) ||
is(T
== struct) ||
is(T
== union))
2579 enum isNested
= __traits(isNested
, T
);
2586 static assert(!isNested
!S
);
2589 struct NestedStruct
{ void f() { ++i
; } }
2590 static assert(isNested
!NestedStruct
);
2594 Determines whether `T` or any of its representation types
2595 have a context pointer.
2597 template hasNested(T
)
2599 import std
.meta
: Filter
;
2601 static if (isStaticArray
!T
&& T
.length
)
2602 enum hasNested
= hasNested
!(typeof(T
.init
[0]));
2603 else static if (is(T
== class) ||
is(T
== struct) ||
is(T
== union))
2605 // prevent infinite recursion for class with member of same type
2606 enum notSame(U
) = !is(immutable T
== immutable U
);
2607 enum hasNested
= isNested
!T ||
2608 anySatisfy
!(.hasNested
, Filter
!(notSame
, Fields
!T
));
2611 enum hasNested
= false;
2620 struct NS
{ void f() { ++i
; } }
2622 static assert(!hasNested
!(S
[2]));
2623 static assert(hasNested
!(NS
[2]));
2628 static assert(!__traits(compiles
, isNested
!int));
2629 static assert(!hasNested
!int);
2631 static struct StaticStruct
{ }
2632 static assert(!isNested
!StaticStruct
);
2633 static assert(!hasNested
!StaticStruct
);
2636 struct NestedStruct
{ void f() { ++i
; } }
2637 static assert( isNested
!NestedStruct
);
2638 static assert( hasNested
!NestedStruct
);
2639 static assert( isNested
!(immutable NestedStruct
));
2640 static assert( hasNested
!(immutable NestedStruct
));
2642 static assert(!__traits(compiles
, isNested
!(NestedStruct
[1])));
2643 static assert( hasNested
!(NestedStruct
[1]));
2644 static assert(!hasNested
!(NestedStruct
[0]));
2646 struct S1
{ NestedStruct nested
; }
2647 static assert(!isNested
!S1
);
2648 static assert( hasNested
!S1
);
2650 static struct S2
{ NestedStruct nested
; }
2651 static assert(!isNested
!S2
);
2652 static assert( hasNested
!S2
);
2654 static struct S3
{ NestedStruct
[0] nested
; }
2655 static assert(!isNested
!S3
);
2656 static assert(!hasNested
!S3
);
2658 static union U
{ NestedStruct nested
; }
2659 static assert(!isNested
!U
);
2660 static assert( hasNested
!U
);
2662 static class StaticClass
{ }
2663 static assert(!isNested
!StaticClass
);
2664 static assert(!hasNested
!StaticClass
);
2666 class NestedClass
{ void f() { ++i
; } }
2667 static assert( isNested
!NestedClass
);
2668 static assert( hasNested
!NestedClass
);
2669 static assert( isNested
!(immutable NestedClass
));
2670 static assert( hasNested
!(immutable NestedClass
));
2672 static assert(!__traits(compiles
, isNested
!(NestedClass
[1])));
2673 static assert( hasNested
!(NestedClass
[1]));
2674 static assert(!hasNested
!(NestedClass
[0]));
2680 static assert(!hasNested
!A
);
2685 * Get as a tuple the types of the fields of a struct, class, or union.
2686 * This consists of the fields that take up memory space,
2687 * excluding the hidden fields like the virtual function
2688 * table pointer or a context pointer for nested types.
2689 * If `T` isn't a struct, class, interface or union returns a tuple
2690 * with one element `T`.
2693 * - Returned `AliasSeq!(Interface)` for interfaces prior to 2.097
2697 import core
.internal
.traits
: _Fields
= Fields
;
2698 alias Fields
= _Fields
!T
;
2704 import std
.meta
: AliasSeq
;
2705 struct S
{ int x
; float y
; }
2706 static assert(is(Fields
!S
== AliasSeq
!(int, float)));
2710 * Alternate name for $(LREF Fields), kept for legacy compatibility.
2712 alias FieldTypeTuple
= Fields
;
2716 static assert(is(FieldTypeTuple
!int == AliasSeq
!int));
2718 static struct StaticStruct1
{ }
2719 static assert(is(FieldTypeTuple
!StaticStruct1
== AliasSeq
!()));
2721 static struct StaticStruct2
{ int a
, b
; }
2722 static assert(is(FieldTypeTuple
!StaticStruct2
== AliasSeq
!(int, int)));
2726 struct NestedStruct1
{ void f() { ++i
; } }
2727 static assert(is(FieldTypeTuple
!NestedStruct1
== AliasSeq
!()));
2729 struct NestedStruct2
{ int a
; void f() { ++i
; } }
2730 static assert(is(FieldTypeTuple
!NestedStruct2
== AliasSeq
!int));
2732 class NestedClass
{ int a
; void f() { ++i
; } }
2733 static assert(is(FieldTypeTuple
!NestedClass
== AliasSeq
!int));
2735 static interface I
{}
2736 static assert(is(Fields
!I
== AliasSeq
!()));
2739 //Required for FieldNameTuple
2740 private enum NameOf(alias T
) = T
.stringof
;
2743 * Get as an expression tuple the names of the fields of a struct, class, or
2744 * union. This consists of the fields that take up memory space, excluding the
2745 * hidden fields like the virtual function table pointer or a context pointer
2747 * Inherited fields (for classes) are not included.
2748 * If `T` isn't a struct, class, interface or union, an
2749 * expression tuple with an empty string is returned.
2752 * - Returned `AliasSeq!""` for interfaces prior to 2.097
2754 template FieldNameTuple(T
)
2756 import std
.meta
: staticMap
;
2757 static if (is(T
== struct) ||
is(T
== union))
2758 alias FieldNameTuple
= staticMap
!(NameOf
, T
.tupleof
[0 .. $ - isNested
!T
]);
2759 else static if (is(T
== class) ||
is(T
== interface))
2760 alias FieldNameTuple
= staticMap
!(NameOf
, T
.tupleof
);
2762 alias FieldNameTuple
= AliasSeq
!"";
2768 import std
.meta
: AliasSeq
;
2769 struct S
{ int x
; float y
; }
2770 static assert(FieldNameTuple
!S
== AliasSeq
!("x", "y"));
2771 static assert(FieldNameTuple
!int == AliasSeq
!"");
2776 static assert(FieldNameTuple
!int == AliasSeq
!"");
2778 static struct StaticStruct1
{ }
2779 static assert(is(FieldNameTuple
!StaticStruct1
== AliasSeq
!()));
2781 static struct StaticStruct2
{ int a
, b
; }
2782 static assert(FieldNameTuple
!StaticStruct2
== AliasSeq
!("a", "b"));
2784 static class StaticClass1
{ }
2785 static assert(is(FieldNameTuple
!StaticClass1
== AliasSeq
!()));
2787 static class StaticClass2
: StaticClass1
{ int a
, b
; }
2788 static assert(FieldNameTuple
!StaticClass2
== AliasSeq
!("a", "b"));
2790 static class StaticClass3
: StaticClass2
{ int c
; }
2791 static assert(FieldNameTuple
!StaticClass3
== AliasSeq
!("c"));
2795 struct NestedStruct1
{ void f() { ++i
; } }
2796 static assert(is(FieldNameTuple
!NestedStruct1
== AliasSeq
!()));
2798 struct NestedStruct2
{ int a
; void f() { ++i
; } }
2799 static assert(FieldNameTuple
!NestedStruct2
== AliasSeq
!"a");
2801 class NestedClass
{ int a
; void f() { ++i
; } }
2802 static assert(FieldNameTuple
!NestedClass
== AliasSeq
!"a");
2805 static assert(FieldNameTuple
!I
== AliasSeq
!());
2810 Get the primitive types of the fields of a struct or class, in
2813 template RepresentationTypeTuple(T
)
2815 static if (is(T
== struct) ||
is(T
== union) ||
is(T
== class))
2817 alias RepresentationTypeTuple
= staticMapMeta
!(RepresentationTypeTupleImpl
, FieldTypeTuple
!T
);
2821 alias RepresentationTypeTuple
= RepresentationTypeTupleImpl
!T
;
2828 struct S1
{ int a
; float b
; }
2829 struct S2
{ char[] a
; union { S1 b
; S1
* c
; } }
2830 alias R
= RepresentationTypeTuple
!S2
;
2831 assert(R
.length
== 4
2832 && is(R
[0] == char[]) && is(R
[1] == int)
2833 && is(R
[2] == float) && is(R
[3] == S1
*));
2838 alias S1
= RepresentationTypeTuple
!int;
2839 static assert(is(S1
== AliasSeq
!int));
2841 struct S2
{ int a
; }
2842 struct S3
{ int a
; char b
; }
2843 struct S4
{ S1 a
; int b
; S3 c
; }
2844 static assert(is(RepresentationTypeTuple
!S2
== AliasSeq
!int));
2845 static assert(is(RepresentationTypeTuple
!S3
== AliasSeq
!(int, char)));
2846 static assert(is(RepresentationTypeTuple
!S4
== AliasSeq
!(int, int, int, char)));
2848 struct S11
{ int a
; float b
; }
2849 struct S21
{ char[] a
; union { S11 b
; S11
* c
; } }
2850 alias R
= RepresentationTypeTuple
!S21
;
2851 assert(R
.length
== 4
2852 && is(R
[0] == char[]) && is(R
[1] == int)
2853 && is(R
[2] == float) && is(R
[3] == S11
*));
2855 class C
{ int a
; float b
; }
2856 alias R1
= RepresentationTypeTuple
!C
;
2857 static assert(R1
.length
== 2 && is(R1
[0] == int) && is(R1
[1] == float));
2859 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
2860 import std
.typecons
: Rebindable
;
2862 struct S5
{ int a
; Rebindable
!(immutable Object
) b
; }
2863 alias R2
= RepresentationTypeTuple
!S5
;
2864 static assert(R2
.length
== 2 && is(R2
[0] == int) && is(R2
[1] == immutable(Object
)));
2866 static assert(is(RepresentationTypeTuple
!noreturn
== AliasSeq
!noreturn
));
2871 struct VeryLargeType
2873 import std
.format
: format
;
2874 import std
.range
: iota
;
2876 static foreach (i
; 500.iota
)
2878 mixin(format
!"int v%s;"(i
));
2882 alias BigList
= RepresentationTypeTuple
!VeryLargeType
;
2885 private template RepresentationTypeTupleImpl(T
)
2887 import std
.typecons
: Rebindable
;
2889 static if (is(immutable T
== immutable Rebindable
!R
, R
))
2891 alias RepresentationTypeTupleImpl
2892 = staticMapMeta
!(.RepresentationTypeTupleImpl
, RepresentationTypeTupleImpl
!R
);
2894 else static if (is(T
== struct) ||
is(T
== union))
2896 // @@@BUG@@@ this should work
2897 //alias .RepresentationTypes!(T[0].tupleof)
2898 // RepresentationTypes;
2899 alias RepresentationTypeTupleImpl
2900 = staticMapMeta
!(.RepresentationTypeTupleImpl
, FieldTypeTuple
!(T
));
2904 alias RepresentationTypeTupleImpl
2910 Statically evaluates to `true` if and only if `T`'s
2911 representation contains at least one field of pointer or array type.
2912 Members of class types are not considered raw pointers. Pointers to
2913 immutable objects are not considered raw aliasing.
2915 private template hasRawAliasing(T
)
2917 enum hasRawAliasing
= anySatisfy
!(hasRawAliasingImpl
, RepresentationTypeTuple
!T
);
2924 static assert(!hasRawAliasing
!int);
2925 static assert( hasRawAliasing
!(char*));
2926 // references aren't raw pointers
2927 static assert(!hasRawAliasing
!Object
);
2928 // built-in arrays do contain raw pointers
2929 static assert( hasRawAliasing
!(int[]));
2930 // aggregate of simple types
2931 struct S1
{ int a
; double b
; }
2932 static assert(!hasRawAliasing
!S1
);
2933 // indirect aggregation
2934 struct S2
{ S1 a
; double b
; }
2935 static assert(!hasRawAliasing
!S2
);
2938 // https://issues.dlang.org/show_bug.cgi?id=19228
2945 static assert(hasRawAliasing
!C
);
2950 // struct with a pointer member
2951 struct S3
{ int a
; double * b
; }
2952 static assert( hasRawAliasing
!S3
);
2953 // struct with an indirect pointer member
2954 struct S4
{ S3 a
; double b
; }
2955 static assert( hasRawAliasing
!S4
);
2956 struct S5
{ int a
; Object z
; int c
; }
2957 static assert( hasRawAliasing
!S3
);
2958 static assert( hasRawAliasing
!S4
);
2959 static assert(!hasRawAliasing
!S5
);
2961 union S6
{ int a
; int b
; }
2962 union S7
{ int a
; int * b
; }
2963 static assert(!hasRawAliasing
!S6
);
2964 static assert( hasRawAliasing
!S7
);
2966 static assert(!hasRawAliasing
!(void delegate()));
2967 static assert(!hasRawAliasing
!(void delegate() const));
2968 static assert(!hasRawAliasing
!(void delegate() immutable));
2969 static assert(!hasRawAliasing
!(void delegate() shared));
2970 static assert(!hasRawAliasing
!(void delegate() shared const));
2971 static assert(!hasRawAliasing
!(const(void delegate())));
2972 static assert(!hasRawAliasing
!(immutable(void delegate())));
2974 struct S8
{ void delegate() a
; int b
; Object c
; }
2975 class S12
{ typeof(S8
.tupleof
) a
; }
2976 class S13
{ typeof(S8
.tupleof
) a
; int* b
; }
2977 static assert(!hasRawAliasing
!S8
);
2978 static assert(!hasRawAliasing
!S12
);
2979 static assert( hasRawAliasing
!S13
);
2982 static assert(!hasRawAliasing
!S9
);
2985 struct S10
{ S7 a
; int b
; }
2986 struct S11
{ S6 a
; int b
; }
2987 static assert( hasRawAliasing
!S10
);
2988 static assert(!hasRawAliasing
!S11
);
2990 static assert( hasRawAliasing
!(int[string
]));
2991 static assert(!hasRawAliasing
!(immutable(int[string
])));
2994 private template hasRawAliasingImpl(T
)
2996 static if (is(T foo
: U
*, U
) && !isFunctionPointer
!T
)
2997 enum hasRawAliasingImpl
= !is(U
== immutable);
2998 else static if (is(T foo
: U
[N
], U
, size_t N
))
2999 // separate static ifs to avoid forward reference
3000 static if (is(U
== class) ||
is(U
== interface))
3001 enum hasRawAliasingImpl
= false;
3003 enum hasRawAliasingImpl
= hasRawAliasingImpl
!U
;
3004 else static if (is(T foo
: U
[], U
) && !isStaticArray
!(T
))
3005 enum hasRawAliasingImpl
= !is(U
== immutable);
3006 else static if (isAssociativeArray
!(T
))
3007 enum hasRawAliasingImpl
= !is(T
== immutable);
3009 enum hasRawAliasingImpl
= false;
3013 Statically evaluates to `true` if and only if `T`'s
3014 representation contains at least one non-shared field of pointer or
3015 array type. Members of class types are not considered raw pointers.
3016 Pointers to immutable objects are not considered raw aliasing.
3018 private template hasRawUnsharedAliasing(T
)
3020 enum hasRawUnsharedAliasing
= anySatisfy
!(hasRawUnsharedAliasingImpl
, RepresentationTypeTuple
!T
);
3027 static assert(!hasRawUnsharedAliasing
!int);
3028 static assert( hasRawUnsharedAliasing
!(char*));
3029 static assert(!hasRawUnsharedAliasing
!(shared char*));
3030 // references aren't raw pointers
3031 static assert(!hasRawUnsharedAliasing
!Object
);
3032 // built-in arrays do contain raw pointers
3033 static assert( hasRawUnsharedAliasing
!(int[]));
3034 static assert(!hasRawUnsharedAliasing
!(shared int[]));
3035 // aggregate of simple types
3036 struct S1
{ int a
; double b
; }
3037 static assert(!hasRawUnsharedAliasing
!S1
);
3038 // indirect aggregation
3039 struct S2
{ S1 a
; double b
; }
3040 static assert(!hasRawUnsharedAliasing
!S2
);
3041 // struct with a pointer member
3042 struct S3
{ int a
; double * b
; }
3043 static assert( hasRawUnsharedAliasing
!S3
);
3044 struct S4
{ int a
; shared double * b
; }
3045 static assert(!hasRawUnsharedAliasing
!S4
);
3050 // struct with a pointer member
3051 struct S3
{ int a
; double * b
; }
3052 static assert( hasRawUnsharedAliasing
!S3
);
3053 struct S4
{ int a
; shared double * b
; }
3054 static assert(!hasRawUnsharedAliasing
!S4
);
3055 // struct with an indirect pointer member
3056 struct S5
{ S3 a
; double b
; }
3057 static assert( hasRawUnsharedAliasing
!S5
);
3058 struct S6
{ S4 a
; double b
; }
3059 static assert(!hasRawUnsharedAliasing
!S6
);
3060 struct S7
{ int a
; Object z
; int c
; }
3061 static assert( hasRawUnsharedAliasing
!S5
);
3062 static assert(!hasRawUnsharedAliasing
!S6
);
3063 static assert(!hasRawUnsharedAliasing
!S7
);
3065 union S8
{ int a
; int b
; }
3066 union S9
{ int a
; int* b
; }
3067 union S10
{ int a
; shared int* b
; }
3068 static assert(!hasRawUnsharedAliasing
!S8
);
3069 static assert( hasRawUnsharedAliasing
!S9
);
3070 static assert(!hasRawUnsharedAliasing
!S10
);
3072 static assert(!hasRawUnsharedAliasing
!(void delegate()));
3073 static assert(!hasRawUnsharedAliasing
!(void delegate() const));
3074 static assert(!hasRawUnsharedAliasing
!(void delegate() immutable));
3075 static assert(!hasRawUnsharedAliasing
!(void delegate() shared));
3076 static assert(!hasRawUnsharedAliasing
!(void delegate() shared const));
3077 static assert(!hasRawUnsharedAliasing
!(const(void delegate())));
3078 static assert(!hasRawUnsharedAliasing
!(const(void delegate() const)));
3079 static assert(!hasRawUnsharedAliasing
!(const(void delegate() immutable)));
3080 static assert(!hasRawUnsharedAliasing
!(const(void delegate() shared)));
3081 static assert(!hasRawUnsharedAliasing
!(const(void delegate() shared const)));
3082 static assert(!hasRawUnsharedAliasing
!(immutable(void delegate())));
3083 static assert(!hasRawUnsharedAliasing
!(immutable(void delegate() const)));
3084 static assert(!hasRawUnsharedAliasing
!(immutable(void delegate() immutable)));
3085 static assert(!hasRawUnsharedAliasing
!(immutable(void delegate() shared)));
3086 static assert(!hasRawUnsharedAliasing
!(immutable(void delegate() shared const)));
3087 static assert(!hasRawUnsharedAliasing
!(shared(void delegate())));
3088 static assert(!hasRawUnsharedAliasing
!(shared(void delegate() const)));
3089 static assert(!hasRawUnsharedAliasing
!(shared(void delegate() immutable)));
3090 static assert(!hasRawUnsharedAliasing
!(shared(void delegate() shared)));
3091 static assert(!hasRawUnsharedAliasing
!(shared(void delegate() shared const)));
3092 static assert(!hasRawUnsharedAliasing
!(shared(const(void delegate()))));
3093 static assert(!hasRawUnsharedAliasing
!(shared(const(void delegate() const))));
3094 static assert(!hasRawUnsharedAliasing
!(shared(const(void delegate() immutable))));
3095 static assert(!hasRawUnsharedAliasing
!(shared(const(void delegate() shared))));
3096 static assert(!hasRawUnsharedAliasing
!(shared(const(void delegate() shared const))));
3097 static assert(!hasRawUnsharedAliasing
!(void function()));
3100 static assert(!hasRawUnsharedAliasing
!S13
);
3103 struct S14
{ S9 a
; int b
; }
3104 struct S15
{ S10 a
; int b
; }
3105 struct S16
{ S6 a
; int b
; }
3106 static assert( hasRawUnsharedAliasing
!S14
);
3107 static assert(!hasRawUnsharedAliasing
!S15
);
3108 static assert(!hasRawUnsharedAliasing
!S16
);
3110 static assert( hasRawUnsharedAliasing
!(int[string
]));
3111 static assert(!hasRawUnsharedAliasing
!(shared(int[string
])));
3112 static assert(!hasRawUnsharedAliasing
!(immutable(int[string
])));
3116 void delegate() shared a
;
3117 void delegate() immutable b
;
3118 void delegate() shared const c
;
3119 shared(void delegate()) d
;
3120 shared(void delegate() shared) e
;
3121 shared(void delegate() immutable) f
;
3122 shared(void delegate() shared const) g
;
3123 immutable(void delegate()) h
;
3124 immutable(void delegate() shared) i
;
3125 immutable(void delegate() immutable) j
;
3126 immutable(void delegate() shared const) k
;
3127 shared(const(void delegate())) l
;
3128 shared(const(void delegate() shared)) m
;
3129 shared(const(void delegate() immutable)) n
;
3130 shared(const(void delegate() shared const)) o
;
3132 struct S18
{ typeof(S17
.tupleof
) a
; void delegate() p
; }
3133 struct S19
{ typeof(S17
.tupleof
) a
; Object p
; }
3134 struct S20
{ typeof(S17
.tupleof
) a
; int* p
; }
3135 class S21
{ typeof(S17
.tupleof
) a
; }
3136 class S22
{ typeof(S17
.tupleof
) a
; void delegate() p
; }
3137 class S23
{ typeof(S17
.tupleof
) a
; Object p
; }
3138 class S24
{ typeof(S17
.tupleof
) a
; int* p
; }
3139 static assert(!hasRawUnsharedAliasing
!S17
);
3140 static assert(!hasRawUnsharedAliasing
!(immutable(S17
)));
3141 static assert(!hasRawUnsharedAliasing
!(shared(S17
)));
3142 static assert(!hasRawUnsharedAliasing
!S18
);
3143 static assert(!hasRawUnsharedAliasing
!(immutable(S18
)));
3144 static assert(!hasRawUnsharedAliasing
!(shared(S18
)));
3145 static assert(!hasRawUnsharedAliasing
!S19
);
3146 static assert(!hasRawUnsharedAliasing
!(immutable(S19
)));
3147 static assert(!hasRawUnsharedAliasing
!(shared(S19
)));
3148 static assert( hasRawUnsharedAliasing
!S20
);
3149 static assert(!hasRawUnsharedAliasing
!(immutable(S20
)));
3150 static assert(!hasRawUnsharedAliasing
!(shared(S20
)));
3151 static assert(!hasRawUnsharedAliasing
!S21
);
3152 static assert(!hasRawUnsharedAliasing
!(immutable(S21
)));
3153 static assert(!hasRawUnsharedAliasing
!(shared(S21
)));
3154 static assert(!hasRawUnsharedAliasing
!S22
);
3155 static assert(!hasRawUnsharedAliasing
!(immutable(S22
)));
3156 static assert(!hasRawUnsharedAliasing
!(shared(S22
)));
3157 static assert(!hasRawUnsharedAliasing
!S23
);
3158 static assert(!hasRawUnsharedAliasing
!(immutable(S23
)));
3159 static assert(!hasRawUnsharedAliasing
!(shared(S23
)));
3160 static assert( hasRawUnsharedAliasing
!S24
);
3161 static assert(!hasRawUnsharedAliasing
!(immutable(S24
)));
3162 static assert(!hasRawUnsharedAliasing
!(shared(S24
)));
3167 static assert(!hasRawUnsharedAliasing
!S25
);
3168 static assert(!hasRawUnsharedAliasing
!S26
);
3169 static assert(!hasRawUnsharedAliasing
!S27
);
3170 static assert(!hasRawUnsharedAliasing
!S28
);
3173 private template hasRawUnsharedAliasingImpl(T
)
3175 static if (is(T foo
: U
*, U
) && !isFunctionPointer
!T
)
3176 enum hasRawUnsharedAliasingImpl
= !is(U
== immutable) && !is(U
== shared);
3177 else static if (is(T foo
: U
[], U
) && !isStaticArray
!T
)
3178 enum hasRawUnsharedAliasingImpl
= !is(U
== immutable) && !is(U
== shared);
3179 else static if (isAssociativeArray
!T
)
3180 enum hasRawUnsharedAliasingImpl
= !is(T
== immutable) && !is(T
== shared);
3182 enum hasRawUnsharedAliasingImpl
= false;
3186 Statically evaluates to `true` if and only if `T`'s
3187 representation includes at least one non-immutable object reference.
3190 private template hasObjects(T
)
3192 static if (is(T
== struct))
3194 enum hasObjects
= anySatisfy
!(.hasObjects
, RepresentationTypeTuple
!T
);
3198 enum hasObjects
= (is(T
== class) ||
is(T
== interface)) && !is(T
== immutable);
3203 Statically evaluates to `true` if and only if `T`'s
3204 representation includes at least one non-immutable non-shared object
3207 private template hasUnsharedObjects(T
)
3209 static if (is(T
== struct))
3211 enum hasUnsharedObjects
= anySatisfy
!(.hasUnsharedObjects
, RepresentationTypeTuple
!T
);
3215 enum hasUnsharedObjects
= (is(T
== class) ||
is(T
== interface)) &&
3216 !is(T
== immutable) && !is(T
== shared);
3221 Returns `true` if and only if `T`'s representation includes at
3222 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3223 is not immutable;) $(LI an array `U[]` and `U` is not
3224 immutable;) $(LI a reference to a class or interface type `C` and `C` is
3225 not immutable.) $(LI an associative array that is not immutable.)
3228 template hasAliasing(T
...)
3230 enum hasAliasing
= anySatisfy
!(hasAliasingImpl
, T
);
3236 struct S1
{ int a
; Object b
; }
3237 struct S2
{ string a
; }
3238 struct S3
{ int a
; immutable Object b
; }
3239 struct S4
{ float[3] vals
; }
3240 static assert( hasAliasing
!S1
);
3241 static assert(!hasAliasing
!S2
);
3242 static assert(!hasAliasing
!S3
);
3243 static assert(!hasAliasing
!S4
);
3248 static assert( hasAliasing
!(uint[uint]));
3249 static assert(!hasAliasing
!(immutable(uint[uint])));
3250 static assert( hasAliasing
!(void delegate()));
3251 static assert( hasAliasing
!(void delegate() const));
3252 static assert(!hasAliasing
!(void delegate() immutable));
3253 static assert( hasAliasing
!(void delegate() shared));
3254 static assert( hasAliasing
!(void delegate() shared const));
3255 static assert( hasAliasing
!(const(void delegate())));
3256 static assert( hasAliasing
!(const(void delegate() const)));
3257 static assert(!hasAliasing
!(const(void delegate() immutable)));
3258 static assert( hasAliasing
!(const(void delegate() shared)));
3259 static assert( hasAliasing
!(const(void delegate() shared const)));
3260 static assert(!hasAliasing
!(immutable(void delegate())));
3261 static assert(!hasAliasing
!(immutable(void delegate() const)));
3262 static assert(!hasAliasing
!(immutable(void delegate() immutable)));
3263 static assert(!hasAliasing
!(immutable(void delegate() shared)));
3264 static assert(!hasAliasing
!(immutable(void delegate() shared const)));
3265 static assert( hasAliasing
!(shared(const(void delegate()))));
3266 static assert( hasAliasing
!(shared(const(void delegate() const))));
3267 static assert(!hasAliasing
!(shared(const(void delegate() immutable))));
3268 static assert( hasAliasing
!(shared(const(void delegate() shared))));
3269 static assert( hasAliasing
!(shared(const(void delegate() shared const))));
3270 static assert(!hasAliasing
!(void function()));
3273 static assert( hasAliasing
!I
);
3275 import std
.typecons
: Rebindable
;
3276 static assert( hasAliasing
!(Rebindable
!(const Object
)));
3277 static assert(!hasAliasing
!(Rebindable
!(immutable Object
)));
3278 static assert( hasAliasing
!(Rebindable
!(shared Object
)));
3279 static assert( hasAliasing
!(Rebindable
!Object
));
3283 void delegate() immutable b
;
3284 shared(void delegate() immutable) f
;
3285 immutable(void delegate() immutable) j
;
3286 shared(const(void delegate() immutable)) n
;
3288 struct S6
{ typeof(S5
.tupleof
) a
; void delegate() p
; }
3289 static assert(!hasAliasing
!S5
);
3290 static assert( hasAliasing
!S6
);
3292 struct S7
{ void delegate() a
; int b
; Object c
; }
3293 class S8
{ int a
; int b
; }
3294 class S9
{ typeof(S8
.tupleof
) a
; }
3295 class S10
{ typeof(S8
.tupleof
) a
; int* b
; }
3296 static assert( hasAliasing
!S7
);
3297 static assert( hasAliasing
!S8
);
3298 static assert( hasAliasing
!S9
);
3299 static assert( hasAliasing
!S10
);
3304 static assert(!hasAliasing
!S11
);
3305 static assert( hasAliasing
!S12
);
3306 static assert( hasAliasing
!S13
);
3307 static assert(!hasAliasing
!S14
);
3309 class S15
{ S15
[1] a
; }
3310 static assert( hasAliasing
!S15
);
3311 static assert(!hasAliasing
!(immutable(S15
)));
3313 static assert(!hasAliasing
!noreturn
);
3316 private template hasAliasingImpl(T
)
3318 import std
.typecons
: Rebindable
;
3320 static if (is(immutable T
== immutable Rebindable
!R
, R
))
3322 enum hasAliasingImpl
= hasAliasingImpl
!R
;
3326 template isAliasingDelegate(T
)
3328 enum isAliasingDelegate
= isDelegate
!T
3329 && !is(T
== immutable)
3330 && !is(FunctionTypeOf
!T
== immutable);
3332 enum hasAliasingImpl
= hasRawAliasing
!T || hasObjects
!T ||
3333 anySatisfy
!(isAliasingDelegate
, T
, RepresentationTypeTuple
!T
);
3338 Returns `true` if and only if `T`'s representation includes at
3339 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an
3340 array `U[]`;) $(LI a reference to a class type `C`;)
3341 $(LI an associative array;) $(LI a delegate;)
3342 $(LI a [context pointer][isNested].))
3344 template hasIndirections(T
)
3346 import core
.internal
.traits
: _hasIndirections
= hasIndirections
;
3347 alias hasIndirections
= _hasIndirections
!T
;
3353 static assert( hasIndirections
!(int[string
]));
3354 static assert( hasIndirections
!(void delegate()));
3355 static assert( hasIndirections
!(void delegate() immutable));
3356 static assert( hasIndirections
!(immutable(void delegate())));
3357 static assert( hasIndirections
!(immutable(void delegate() immutable)));
3359 static assert(!hasIndirections
!(void function()));
3360 static assert( hasIndirections
!(void*[1]));
3361 static assert(!hasIndirections
!(byte[1]));
3366 // void static array hides actual type of bits, so "may have indirections".
3367 static assert( hasIndirections
!(void[1]));
3370 struct S2
{ int a
; }
3371 struct S3
{ int a
; int b
; }
3372 struct S4
{ int a
; int* b
; }
3373 struct S5
{ int a
; Object b
; }
3374 struct S6
{ int a
; string b
; }
3375 struct S7
{ int a
; immutable Object b
; }
3376 struct S8
{ int a
; immutable I b
; }
3377 struct S9
{ int a
; void delegate() b
; }
3378 struct S10
{ int a
; immutable(void delegate()) b
; }
3379 struct S11
{ int a
; void delegate() immutable b
; }
3380 struct S12
{ int a
; immutable(void delegate() immutable) b
; }
3382 class S14
{ int a
; }
3383 class S15
{ int a
; int b
; }
3384 class S16
{ int a
; Object b
; }
3385 class S17
{ string a
; }
3386 class S18
{ int a
; immutable Object b
; }
3387 class S19
{ int a
; immutable(void delegate() immutable) b
; }
3389 union S21
{ int a
; }
3390 union S22
{ int a
; int b
; }
3391 union S23
{ int a
; Object b
; }
3392 union S24
{ string a
; }
3393 union S25
{ int a
; immutable Object b
; }
3394 union S26
{ int a
; immutable(void delegate() immutable) b
; }
3395 static assert( hasIndirections
!I
);
3396 static assert(!hasIndirections
!S1
);
3397 static assert(!hasIndirections
!S2
);
3398 static assert(!hasIndirections
!S3
);
3399 static assert( hasIndirections
!S4
);
3400 static assert( hasIndirections
!S5
);
3401 static assert( hasIndirections
!S6
);
3402 static assert( hasIndirections
!S7
);
3403 static assert( hasIndirections
!S8
);
3404 static assert( hasIndirections
!S9
);
3405 static assert( hasIndirections
!S10
);
3406 static assert( hasIndirections
!S12
);
3407 static assert( hasIndirections
!S13
);
3408 static assert( hasIndirections
!S14
);
3409 static assert( hasIndirections
!S15
);
3410 static assert( hasIndirections
!S16
);
3411 static assert( hasIndirections
!S17
);
3412 static assert( hasIndirections
!S18
);
3413 static assert( hasIndirections
!S19
);
3414 static assert(!hasIndirections
!S20
);
3415 static assert(!hasIndirections
!S21
);
3416 static assert(!hasIndirections
!S22
);
3417 static assert( hasIndirections
!S23
);
3418 static assert( hasIndirections
!S24
);
3419 static assert( hasIndirections
!S25
);
3420 static assert( hasIndirections
!S26
);
3422 struct HasContextPointer
{ int opCall() { return ++local
; } }
3423 static assert(hasIndirections
!HasContextPointer
);
3425 static assert(!hasIndirections
!noreturn
);
3428 // https://issues.dlang.org/show_bug.cgi?id=12000
3433 static assert(hasIndirections
!T
);
3445 Returns `true` if and only if `T`'s representation includes at
3446 least one of the following: $(OL $(LI a raw pointer `U*` and `U`
3447 is not immutable or shared;) $(LI an array `U[]` and `U` is not
3448 immutable or shared;) $(LI a reference to a class type `C` and
3449 `C` is not immutable or shared.) $(LI an associative array that is not
3450 immutable or shared.) $(LI a delegate that is not shared.))
3453 template hasUnsharedAliasing(T
...)
3455 enum hasUnsharedAliasing
= anySatisfy
!(hasUnsharedAliasingImpl
, T
);
3461 struct S1
{ int a
; Object b
; }
3462 struct S2
{ string a
; }
3463 struct S3
{ int a
; immutable Object b
; }
3464 static assert( hasUnsharedAliasing
!S1
);
3465 static assert(!hasUnsharedAliasing
!S2
);
3466 static assert(!hasUnsharedAliasing
!S3
);
3468 struct S4
{ int a
; shared Object b
; }
3469 struct S5
{ char[] a
; }
3470 struct S6
{ shared char[] b
; }
3471 struct S7
{ float[3] vals
; }
3472 static assert(!hasUnsharedAliasing
!S4
);
3473 static assert( hasUnsharedAliasing
!S5
);
3474 static assert(!hasUnsharedAliasing
!S6
);
3475 static assert(!hasUnsharedAliasing
!S7
);
3480 /* https://issues.dlang.org/show_bug.cgi?id=6642 */
3481 import std
.typecons
: Rebindable
;
3482 struct S8
{ int a
; Rebindable
!(immutable Object
) b
; }
3483 static assert(!hasUnsharedAliasing
!S8
);
3485 static assert( hasUnsharedAliasing
!(uint[uint]));
3487 static assert( hasUnsharedAliasing
!(void delegate()));
3488 static assert( hasUnsharedAliasing
!(void delegate() const));
3489 static assert(!hasUnsharedAliasing
!(void delegate() immutable));
3490 static assert(!hasUnsharedAliasing
!(void delegate() shared));
3491 static assert(!hasUnsharedAliasing
!(void delegate() shared const));
3496 import std
.typecons
: Rebindable
;
3497 static assert( hasUnsharedAliasing
!(const(void delegate())));
3498 static assert( hasUnsharedAliasing
!(const(void delegate() const)));
3499 static assert(!hasUnsharedAliasing
!(const(void delegate() immutable)));
3500 static assert(!hasUnsharedAliasing
!(const(void delegate() shared)));
3501 static assert(!hasUnsharedAliasing
!(const(void delegate() shared const)));
3502 static assert(!hasUnsharedAliasing
!(immutable(void delegate())));
3503 static assert(!hasUnsharedAliasing
!(immutable(void delegate() const)));
3504 static assert(!hasUnsharedAliasing
!(immutable(void delegate() immutable)));
3505 static assert(!hasUnsharedAliasing
!(immutable(void delegate() shared)));
3506 static assert(!hasUnsharedAliasing
!(immutable(void delegate() shared const)));
3507 static assert(!hasUnsharedAliasing
!(shared(void delegate())));
3508 static assert(!hasUnsharedAliasing
!(shared(void delegate() const)));
3509 static assert(!hasUnsharedAliasing
!(shared(void delegate() immutable)));
3510 static assert(!hasUnsharedAliasing
!(shared(void delegate() shared)));
3511 static assert(!hasUnsharedAliasing
!(shared(void delegate() shared const)));
3512 static assert(!hasUnsharedAliasing
!(shared(const(void delegate()))));
3513 static assert(!hasUnsharedAliasing
!(shared(const(void delegate() const))));
3514 static assert(!hasUnsharedAliasing
!(shared(const(void delegate() immutable))));
3515 static assert(!hasUnsharedAliasing
!(shared(const(void delegate() shared))));
3516 static assert(!hasUnsharedAliasing
!(shared(const(void delegate() shared const))));
3517 static assert(!hasUnsharedAliasing
!(void function()));
3520 static assert(hasUnsharedAliasing
!I
);
3522 static assert( hasUnsharedAliasing
!(Rebindable
!(const Object
)));
3523 static assert(!hasUnsharedAliasing
!(Rebindable
!(immutable Object
)));
3524 static assert(!hasUnsharedAliasing
!(Rebindable
!(shared Object
)));
3525 static assert( hasUnsharedAliasing
!(Rebindable
!Object
));
3527 /* https://issues.dlang.org/show_bug.cgi?id=6979 */
3528 static assert(!hasUnsharedAliasing
!(int, shared(int)*));
3529 static assert( hasUnsharedAliasing
!(int, int*));
3530 static assert( hasUnsharedAliasing
!(int, const(int)[]));
3531 static assert( hasUnsharedAliasing
!(int, shared(int)*, Rebindable
!Object
));
3532 static assert(!hasUnsharedAliasing
!(shared(int)*, Rebindable
!(shared Object
)));
3533 static assert(!hasUnsharedAliasing
!());
3537 void delegate() shared a
;
3538 void delegate() immutable b
;
3539 void delegate() shared const c
;
3540 shared(void delegate()) d
;
3541 shared(void delegate() shared) e
;
3542 shared(void delegate() immutable) f
;
3543 shared(void delegate() shared const) g
;
3544 immutable(void delegate()) h
;
3545 immutable(void delegate() shared) i
;
3546 immutable(void delegate() immutable) j
;
3547 immutable(void delegate() shared const) k
;
3548 shared(const(void delegate())) l
;
3549 shared(const(void delegate() shared)) m
;
3550 shared(const(void delegate() immutable)) n
;
3551 shared(const(void delegate() shared const)) o
;
3553 struct S10
{ typeof(S9
.tupleof
) a
; void delegate() p
; }
3554 struct S11
{ typeof(S9
.tupleof
) a
; Object p
; }
3555 struct S12
{ typeof(S9
.tupleof
) a
; int* p
; }
3556 class S13
{ typeof(S9
.tupleof
) a
; }
3557 class S14
{ typeof(S9
.tupleof
) a
; void delegate() p
; }
3558 class S15
{ typeof(S9
.tupleof
) a
; Object p
; }
3559 class S16
{ typeof(S9
.tupleof
) a
; int* p
; }
3560 static assert(!hasUnsharedAliasing
!S9
);
3561 static assert(!hasUnsharedAliasing
!(immutable(S9
)));
3562 static assert(!hasUnsharedAliasing
!(shared(S9
)));
3563 static assert( hasUnsharedAliasing
!S10
);
3564 static assert(!hasUnsharedAliasing
!(immutable(S10
)));
3565 static assert(!hasUnsharedAliasing
!(shared(S10
)));
3566 static assert( hasUnsharedAliasing
!S11
);
3567 static assert(!hasUnsharedAliasing
!(immutable(S11
)));
3568 static assert(!hasUnsharedAliasing
!(shared(S11
)));
3569 static assert( hasUnsharedAliasing
!S12
);
3570 static assert(!hasUnsharedAliasing
!(immutable(S12
)));
3571 static assert(!hasUnsharedAliasing
!(shared(S12
)));
3572 static assert( hasUnsharedAliasing
!S13
);
3573 static assert(!hasUnsharedAliasing
!(immutable(S13
)));
3574 static assert(!hasUnsharedAliasing
!(shared(S13
)));
3575 static assert( hasUnsharedAliasing
!S14
);
3576 static assert(!hasUnsharedAliasing
!(immutable(S14
)));
3577 static assert(!hasUnsharedAliasing
!(shared(S14
)));
3578 static assert( hasUnsharedAliasing
!S15
);
3579 static assert(!hasUnsharedAliasing
!(immutable(S15
)));
3580 static assert(!hasUnsharedAliasing
!(shared(S15
)));
3581 static assert( hasUnsharedAliasing
!S16
);
3582 static assert(!hasUnsharedAliasing
!(immutable(S16
)));
3583 static assert(!hasUnsharedAliasing
!(shared(S16
)));
3588 static assert(!hasUnsharedAliasing
!S17
);
3589 static assert( hasUnsharedAliasing
!S18
);
3590 static assert( hasUnsharedAliasing
!S19
);
3591 static assert(!hasUnsharedAliasing
!S20
);
3593 static assert(!hasUnsharedAliasing
!noreturn
);
3596 private template hasUnsharedAliasingImpl(T
)
3598 import std
.typecons
: Rebindable
;
3600 static if (is(immutable T
== immutable Rebindable
!R
, R
))
3602 enum hasUnsharedAliasingImpl
= hasUnsharedAliasingImpl
!R
;
3606 template unsharedDelegate(T
)
3608 enum bool unsharedDelegate
= isDelegate
!T
3610 && !is(T
== immutable)
3611 && !is(FunctionTypeOf
!T
== shared)
3612 && !is(FunctionTypeOf
!T
== immutable);
3615 enum hasUnsharedAliasingImpl
=
3616 hasRawUnsharedAliasing
!T ||
3617 anySatisfy
!(unsharedDelegate
, RepresentationTypeTuple
!T
) ||
3618 hasUnsharedObjects
!T
;
3625 True if `S` or any type embedded directly in the representation of `S`
3626 defines an elaborate copy constructor. Elaborate copy constructors are
3627 introduced by defining `this(this)` for a `struct`.
3629 Classes and unions never have elaborate copy constructors.
3631 template hasElaborateCopyConstructor(S
)
3633 import core
.internal
.traits
: hasElabCCtor
= hasElaborateCopyConstructor
;
3634 alias hasElaborateCopyConstructor
= hasElabCCtor
!(S
);
3639 import core
.internal
.traits
: hasElabCCtor
= hasElaborateCopyConstructor
;
3640 alias hasElaborateCopyConstructor
= hasElabCCtor
;
3646 static assert(!hasElaborateCopyConstructor
!int);
3648 static struct S1
{ }
3649 static struct S2
{ this(this) {} }
3650 static struct S3
{ S2 field
; }
3651 static struct S4
{ S3
[1] field
; }
3652 static struct S5
{ S3
[] field
; }
3653 static struct S6
{ S3
[0] field
; }
3654 static struct S7
{ @disable this(); S3 field
; }
3655 static assert(!hasElaborateCopyConstructor
!S1
);
3656 static assert( hasElaborateCopyConstructor
!S2
);
3657 static assert( hasElaborateCopyConstructor
!(immutable S2
));
3658 static assert( hasElaborateCopyConstructor
!S3
);
3659 static assert( hasElaborateCopyConstructor
!(S3
[1]));
3660 static assert(!hasElaborateCopyConstructor
!(S3
[0]));
3661 static assert( hasElaborateCopyConstructor
!S4
);
3662 static assert(!hasElaborateCopyConstructor
!S5
);
3663 static assert(!hasElaborateCopyConstructor
!S6
);
3664 static assert( hasElaborateCopyConstructor
!S7
);
3668 True if `S` or any type directly embedded in the representation of `S`
3669 defines an elaborate assignment. Elaborate assignments are introduced by
3670 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this)))
3671 for a `struct` or when there is a compiler-generated `opAssign`.
3673 A type `S` gets compiler-generated `opAssign` if it has
3674 an elaborate destructor.
3676 Classes and unions never have elaborate assignments.
3678 Note: Structs with (possibly nested) postblit operator(s) will have a
3679 hidden yet elaborate compiler generated assignment operator (unless
3680 explicitly disabled).
3682 template hasElaborateAssign(S
)
3684 static if (isStaticArray
!S
&& S
.length
)
3686 enum bool hasElaborateAssign
= hasElaborateAssign
!(typeof(S
.init
[0]));
3688 else static if (is(S
== struct))
3690 enum hasElaborateAssign
= is(typeof(S
.init
.opAssign(rvalueOf
!S
))) ||
3691 is(typeof(S
.init
.opAssign(lvalueOf
!S
))) ||
3692 anySatisfy
!(.hasElaborateAssign
, FieldTypeTuple
!S
);
3696 enum bool hasElaborateAssign
= false;
3703 static assert(!hasElaborateAssign
!int);
3705 static struct S
{ void opAssign(S
) {} }
3706 static assert( hasElaborateAssign
!S
);
3707 static assert(!hasElaborateAssign
!(const(S
)));
3709 static struct S1
{ void opAssign(ref S1
) {} }
3710 static struct S2
{ void opAssign(int) {} }
3711 static struct S3
{ S s
; }
3712 static assert( hasElaborateAssign
!S1
);
3713 static assert(!hasElaborateAssign
!S2
);
3714 static assert( hasElaborateAssign
!S3
);
3715 static assert( hasElaborateAssign
!(S3
[1]));
3716 static assert(!hasElaborateAssign
!(S3
[0]));
3721 static struct S
{ void opAssign(S
) {} }
3724 void opAssign(U
)(U u
) {}
3725 @disable void opAssign(U
)(ref U u
);
3727 static assert( hasElaborateAssign
!S4
);
3731 void opAssign(U
)(ref U u
) {}
3732 @disable void opAssign(U
)(U u
);
3734 static assert( hasElaborateAssign
!S41
);
3736 static struct S5
{ @disable this(); this(int n
){ s
= S(); } S s
; }
3737 static assert( hasElaborateAssign
!S5
);
3739 static struct S6
{ this(this) {} }
3740 static struct S7
{ this(this) {} @disable void opAssign(S7
); }
3741 static struct S8
{ this(this) {} @disable void opAssign(S8
); void opAssign(int) {} }
3742 static struct S9
{ this(this) {} void opAssign(int) {} }
3743 static struct S10
{ ~this() { } }
3744 static assert( hasElaborateAssign
!S6
);
3745 static assert(!hasElaborateAssign
!S7
);
3746 static assert(!hasElaborateAssign
!S8
);
3747 static assert( hasElaborateAssign
!S9
);
3748 static assert( hasElaborateAssign
!S10
);
3749 static struct SS6
{ S6 s
; }
3750 static struct SS7
{ S7 s
; }
3751 static struct SS8
{ S8 s
; }
3752 static struct SS9
{ S9 s
; }
3753 static assert( hasElaborateAssign
!SS6
);
3754 static assert(!hasElaborateAssign
!SS7
);
3755 static assert(!hasElaborateAssign
!SS8
);
3756 static assert( hasElaborateAssign
!SS9
);
3762 True if `S` or any type directly embedded in the representation
3763 of `S` defines an elaborate destructor. Elaborate destructors
3764 are introduced by defining `~this()` for a $(D
3767 Classes and unions never have elaborate destructors, even
3768 though classes may define `~this()`.
3770 template hasElaborateDestructor(S
)
3772 import core
.internal
.traits
: hasElabDest
= hasElaborateDestructor
;
3773 alias hasElaborateDestructor
= hasElabDest
!(S
);
3778 import core
.internal
.traits
: hasElabDest
= hasElaborateDestructor
;
3779 alias hasElaborateDestructor
= hasElabDest
;
3785 static assert(!hasElaborateDestructor
!int);
3787 static struct S1
{ }
3788 static struct S2
{ ~this() {} }
3789 static struct S3
{ S2 field
; }
3790 static struct S4
{ S3
[1] field
; }
3791 static struct S5
{ S3
[] field
; }
3792 static struct S6
{ S3
[0] field
; }
3793 static struct S7
{ @disable this(); S3 field
; }
3794 static assert(!hasElaborateDestructor
!S1
);
3795 static assert( hasElaborateDestructor
!S2
);
3796 static assert( hasElaborateDestructor
!(immutable S2
));
3797 static assert( hasElaborateDestructor
!S3
);
3798 static assert( hasElaborateDestructor
!(S3
[1]));
3799 static assert(!hasElaborateDestructor
!(S3
[0]));
3800 static assert( hasElaborateDestructor
!S4
);
3801 static assert(!hasElaborateDestructor
!S5
);
3802 static assert(!hasElaborateDestructor
!S6
);
3803 static assert( hasElaborateDestructor
!S7
);
3809 True if `S` or any type embedded directly in the representation of `S`
3810 defines elaborate move semantics. Elaborate move semantics are
3811 introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
3813 Classes and unions never have elaborate move semantics.
3815 template hasElaborateMove(S
)
3817 import core
.internal
.traits
: hasElabMove
= hasElaborateMove
;
3818 alias hasElaborateMove
= hasElabMove
!(S
);
3823 import core
.internal
.traits
: hasElabMove
= hasElaborateMove
;
3824 alias hasElaborateMove
= hasElabMove
;
3830 static assert(!hasElaborateMove
!int);
3832 static struct S1
{ }
3833 static struct S2
{ void opPostMove(ref S2
) {} }
3834 static struct S3
{ void opPostMove(inout ref S3
) inout {} }
3835 static struct S4
{ void opPostMove(const ref S4
) {} }
3836 static struct S5
{ void opPostMove(S5
) {} }
3837 static struct S6
{ void opPostMove(int) {} }
3838 static struct S7
{ S3
[1] field
; }
3839 static struct S8
{ S3
[] field
; }
3840 static struct S9
{ S3
[0] field
; }
3841 static struct S10
{ @disable this(); S3 field
; }
3842 static assert(!hasElaborateMove
!S1
);
3843 static assert( hasElaborateMove
!S2
);
3844 static assert( hasElaborateMove
!S3
);
3845 static assert( hasElaborateMove
!(immutable S3
));
3846 static assert( hasElaborateMove
!S4
);
3847 static assert(!hasElaborateMove
!S5
);
3848 static assert(!hasElaborateMove
!S6
);
3849 static assert( hasElaborateMove
!S7
);
3850 static assert(!hasElaborateMove
!S8
);
3851 static assert(!hasElaborateMove
!S9
);
3852 static assert( hasElaborateMove
!S10
);
3855 package alias Identity(alias A
) = A
;
3858 Yields `true` if and only if `T` is an aggregate that defines
3859 a symbol called `name`.
3861 enum hasMember(T
, string name
) = __traits(hasMember
, T
, name
);
3866 static assert(!hasMember
!(int, "blah"));
3867 struct S1
{ int blah
; }
3868 struct S2
{ int blah(){ return 0; } }
3869 class C1
{ int blah
; }
3870 class C2
{ int blah(){ return 0; } }
3871 static assert(hasMember
!(S1
, "blah"));
3872 static assert(hasMember
!(S2
, "blah"));
3873 static assert(hasMember
!(C1
, "blah"));
3874 static assert(hasMember
!(C2
, "blah"));
3879 // https://issues.dlang.org/show_bug.cgi?id=8321
3892 @property ref inout(T
) payload() inout { return t
; }
3895 static assert(hasMember
!(S
, "x"));
3896 static assert(hasMember
!(S
, "f"));
3897 static assert(hasMember
!(S
, "t"));
3898 static assert(hasMember
!(S
, "T"));
3899 static assert(hasMember
!(R1
!S
, "x"));
3900 static assert(hasMember
!(R1
!S
, "f"));
3901 static assert(hasMember
!(R1
!S
, "t"));
3902 static assert(hasMember
!(R1
!S
, "T"));
3903 static assert(hasMember
!(R2
!S
, "x"));
3904 static assert(hasMember
!(R2
!S
, "f"));
3905 static assert(hasMember
!(R2
!S
, "t"));
3906 static assert(hasMember
!(R2
!S
, "T"));
3913 void opDispatch(string n
, A
)(A dummy
) {}
3915 static assert(hasMember
!(S
, "foo"));
3919 * Whether the symbol represented by the string, member, exists and is a static member of T.
3922 * T = Type containing symbol `member`.
3923 * member = Name of symbol to test that resides in `T`.
3926 * `true` iff `member` exists and is static.
3928 template hasStaticMember(T
, string member
)
3930 static if (__traits(hasMember
, T
, member
))
3932 static if (is(T
== V
*, V
))
3937 import std
.meta
: Alias
;
3938 alias sym
= Alias
!(__traits(getMember
, U
, member
));
3940 static if (__traits(getOverloads
, U
, member
).length
== 0)
3941 enum bool hasStaticMember
= __traits(compiles
, &sym
);
3943 enum bool hasStaticMember
= __traits(isStaticFunction
, sym
);
3947 enum bool hasStaticMember
= false;
3963 static assert( hasStaticMember
!(S
, "sf"));
3964 static assert(!hasStaticMember
!(S
, "f"));
3966 static assert( hasStaticMember
!(S
, "si"));
3967 static assert(!hasStaticMember
!(S
, "i"));
3969 static assert(!hasStaticMember
!(S
, "hello"));
3985 __gshared
int gx
= 0;
3991 static void f2() pure nothrow @nogc @safe;
3995 static void function() fp
;
3996 __gshared
void function() gfp
;
3997 void function() fpm
;
4000 static void delegate() sd
;
4003 void m2() const pure nothrow @nogc @safe;
4005 inout(int) iom() inout;
4006 static inout(int) iosf(inout int x
);
4009 static @property int sp();
4023 __gshared
int gx
= 0;
4029 static void f2() pure nothrow @nogc @safe;
4033 static void function() fp
;
4034 __gshared
void function() gfp
;
4035 void function() fpm
;
4038 static void delegate() sd
;
4041 final void m2() const pure nothrow @nogc @safe;
4043 inout(int) iom() inout { return 10; }
4044 static inout(int) iosf(inout int x
);
4046 @property int p() { return 10; }
4047 static @property int sp();
4050 static assert(!hasStaticMember
!(S
, "na"));
4051 static assert(!hasStaticMember
!(S
, "X"));
4052 static assert(!hasStaticMember
!(S
, "Y"));
4053 static assert(!hasStaticMember
!(S
, "Y.i"));
4054 static assert(!hasStaticMember
!(S
, "S"));
4055 static assert(!hasStaticMember
!(S
, "C"));
4056 static assert( hasStaticMember
!(S
, "sx"));
4057 static assert( hasStaticMember
!(S
, "gx"));
4058 static assert(!hasStaticMember
!(S
, "y"));
4059 static assert( hasStaticMember
!(S
, "sy"));
4060 static assert( hasStaticMember
!(S
, "f"));
4061 static assert( hasStaticMember
!(S
, "f2"));
4062 static assert(!hasStaticMember
!(S
, "dm"));
4063 static assert( hasStaticMember
!(S
, "sd"));
4064 static assert(!hasStaticMember
!(S
, "g"));
4065 static assert( hasStaticMember
!(S
, "fp"));
4066 static assert( hasStaticMember
!(S
, "gfp"));
4067 static assert(!hasStaticMember
!(S
, "fpm"));
4068 static assert(!hasStaticMember
!(S
, "m"));
4069 static assert(!hasStaticMember
!(S
, "m2"));
4070 static assert(!hasStaticMember
!(S
, "iom"));
4071 static assert( hasStaticMember
!(S
, "iosf"));
4072 static assert(!hasStaticMember
!(S
, "p"));
4073 static assert( hasStaticMember
!(S
, "sp"));
4075 static assert(!hasStaticMember
!(C
, "na"));
4076 static assert(!hasStaticMember
!(C
, "X"));
4077 static assert(!hasStaticMember
!(C
, "Y"));
4078 static assert(!hasStaticMember
!(C
, "Y.i"));
4079 static assert(!hasStaticMember
!(C
, "S"));
4080 static assert(!hasStaticMember
!(C
, "C"));
4081 static assert( hasStaticMember
!(C
, "sx"));
4082 static assert( hasStaticMember
!(C
, "gx"));
4083 static assert(!hasStaticMember
!(C
, "y"));
4084 static assert( hasStaticMember
!(C
, "sy"));
4085 static assert( hasStaticMember
!(C
, "f"));
4086 static assert( hasStaticMember
!(C
, "f2"));
4087 static assert(!hasStaticMember
!(C
, "dm"));
4088 static assert( hasStaticMember
!(C
, "sd"));
4089 static assert(!hasStaticMember
!(C
, "g"));
4090 static assert( hasStaticMember
!(C
, "fp"));
4091 static assert( hasStaticMember
!(C
, "gfp"));
4092 static assert(!hasStaticMember
!(C
, "fpm"));
4093 static assert(!hasStaticMember
!(C
, "m"));
4094 static assert(!hasStaticMember
!(C
, "m2"));
4095 static assert(!hasStaticMember
!(C
, "iom"));
4096 static assert( hasStaticMember
!(C
, "iosf"));
4097 static assert(!hasStaticMember
!(C
, "p"));
4098 static assert( hasStaticMember
!(C
, "sp"));
4101 static assert(!hasStaticMember
!(P
, "na"));
4102 static assert(!hasStaticMember
!(P
, "X"));
4103 static assert(!hasStaticMember
!(P
, "Y"));
4104 static assert(!hasStaticMember
!(P
, "Y.i"));
4105 static assert(!hasStaticMember
!(P
, "S"));
4106 static assert(!hasStaticMember
!(P
, "C"));
4107 static assert( hasStaticMember
!(P
, "sx"));
4108 static assert( hasStaticMember
!(P
, "gx"));
4109 static assert(!hasStaticMember
!(P
, "y"));
4110 static assert( hasStaticMember
!(P
, "sy"));
4111 static assert( hasStaticMember
!(P
, "f"));
4112 static assert( hasStaticMember
!(P
, "f2"));
4113 static assert(!hasStaticMember
!(P
, "dm"));
4114 static assert( hasStaticMember
!(P
, "sd"));
4115 static assert(!hasStaticMember
!(P
, "g"));
4116 static assert( hasStaticMember
!(P
, "fp"));
4117 static assert( hasStaticMember
!(P
, "gfp"));
4118 static assert(!hasStaticMember
!(P
, "fpm"));
4119 static assert(!hasStaticMember
!(P
, "m"));
4120 static assert(!hasStaticMember
!(P
, "m2"));
4121 static assert(!hasStaticMember
!(P
, "iom"));
4122 static assert( hasStaticMember
!(P
, "iosf"));
4123 static assert(!hasStaticMember
!(P
, "p"));
4124 static assert( hasStaticMember
!(P
, "sp"));
4128 Retrieves the members of an enumerated type `enum E`.
4131 E = An enumerated type. `E` may have duplicated values.
4134 Static tuple composed of the members of the enumerated type `E`.
4135 The members are arranged in the same order as declared in `E`.
4136 The name of the enum can be found by querying the compiler for the
4137 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`.
4138 For enumerations with unique values, $(REF to, std,conv) can also be used.
4141 An enum can have multiple members which have the same value. If you want
4142 to use EnumMembers to e.g. generate switch cases at compile-time,
4143 you should use the $(REF NoDuplicates, std,meta) template to avoid
4144 generating duplicate switch cases.
4147 Returned values are strictly typed with `E`. Thus, the following code
4148 does not work without the explicit cast:
4149 --------------------
4150 enum E : int { a, b, c }
4151 int[] abc = cast(int[]) [ EnumMembers!E ];
4152 --------------------
4153 Cast is not necessary if the type of the variable is inferred. See the
4156 template EnumMembers(E
)
4159 alias EnumMembers
= AliasSeq
!();
4160 static foreach (M
; __traits(allMembers
, E
))
4161 EnumMembers
= AliasSeq
!(EnumMembers
, __traits(getMember
, E
, M
));
4164 /// Create an array of enumerated values
4173 auto sqrts
= [EnumMembers
!Sqrts
];
4174 assert(sqrts
== [Sqrts
.one
, Sqrts
.two
, Sqrts
.three
]);
4178 A generic function `rank(v)` in the following example uses this
4179 template for finding a member `e` in an enumerated type `E`.
4183 // Returns i if e is the i-th enumerator of E.
4184 static size_t
rank(E
)(E e
)
4187 static foreach (i
, member
; EnumMembers
!E
)
4192 assert(0, "Not an enum member");
4201 assert(rank(Mode
.read
) == 0);
4202 assert(rank(Mode
.write
) == 1);
4203 assert(rank(Mode
.map
) == 2);
4207 Use EnumMembers to generate a switch statement using static foreach.
4212 import std
.conv
: to
;
4215 string calledMethod
;
4216 void foo() @safe { calledMethod
= "foo"; }
4217 void bar() @safe { calledMethod
= "bar"; }
4218 void baz() @safe { calledMethod
= "baz"; }
4221 enum FooEnum
{ foo
, bar
, baz
}
4223 auto var
= FooEnum
.bar
;
4224 auto fooObj
= new FooClass();
4225 s
: final switch (var
)
4227 static foreach (member
; EnumMembers
!FooEnum
)
4229 case member
: // Generate a case for each enum value.
4230 // Call fooObj.{name of enum value}().
4231 __traits(getMember
, fooObj
, to
!string(member
))();
4235 // As we pass in FooEnum.bar, the bar() method gets called.
4236 assert(fooObj
.calledMethod
== "bar");
4242 static assert([ EnumMembers
!A
] == [ A
.a
]);
4243 enum B
{ a
, b
, c
, d
, e
}
4244 static assert([ EnumMembers
!B
] == [ B
.a
, B
.b
, B
.c
, B
.d
, B
.e
]);
4247 @safe unittest // typed enums
4249 enum A
: string
{ a
= "alpha", b
= "beta" }
4250 static assert([ EnumMembers
!A
] == [ A
.a
, A
.b
]);
4255 int opCmp(S rhs
) const nothrow { return value
- rhs
.value
; }
4257 enum B
: S
{ a
= S(1), b
= S(2), c
= S(3) }
4258 static assert([ EnumMembers
!B
] == [ B
.a
, B
.b
, B
.c
]);
4261 @safe unittest // duplicated values
4268 static assert([ EnumMembers
!A
] == [ A
.a
, A
.b
, A
.c
, A
.d
, A
.e
]);
4271 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
4276 string result
= "enum TLAs {";
4277 foreach (c0
; '0'..'2'+1)
4278 foreach (c1
; '0'..'9'+1)
4279 foreach (c2
; '0'..'9'+1)
4280 foreach (c3
; '0'..'9'+1)
4293 static assert(EnumMembers
!TLAs
[0] == TLAs
._0000
);
4294 static assert(EnumMembers
!TLAs
[$-1] == TLAs
._2999
);
4299 enum E
{ member
, a
= 0, b
= 0 }
4300 static assert(__traits(identifier
, EnumMembers
!E
[0]) == "member");
4301 static assert(__traits(identifier
, EnumMembers
!E
[1]) == "a");
4302 static assert(__traits(identifier
, EnumMembers
!E
[2]) == "b");
4306 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4307 // Classes and Interfaces
4308 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4311 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of
4312 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns
4313 * the empty type tuple.
4315 template BaseTypeTuple(A
)
4317 static if (is(A P
== super))
4318 alias BaseTypeTuple
= P
;
4320 static assert(0, "argument is not a class or interface");
4326 import std
.meta
: AliasSeq
;
4330 interface I12
: I1
, I2
{ }
4331 static assert(is(BaseTypeTuple
!I12
== AliasSeq
!(I1
, I2
)));
4333 interface I3
: I1
{ }
4334 interface I123
: I1
, I2
, I3
{ }
4335 static assert(is(BaseTypeTuple
!I123
== AliasSeq
!(I1
, I2
, I3
)));
4343 class C
: A
, I1
, I2
{ }
4345 alias TL
= BaseTypeTuple
!C
;
4346 assert(TL
.length
== 3);
4347 assert(is (TL
[0] == A
));
4348 assert(is (TL
[1] == I1
));
4349 assert(is (TL
[2] == I2
));
4351 assert(BaseTypeTuple
!Object
.length
== 0);
4355 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class,
4356 * in decreasing order. Interfaces are not included. $(D_PARAM
4357 * BaseClassesTuple!Object) yields the empty type tuple.
4359 template BaseClassesTuple(T
)
4362 static if (is(T
== Object
))
4364 alias BaseClassesTuple
= AliasSeq
!();
4366 else static if (is(BaseTypeTuple
!T
[0] == Object
))
4368 alias BaseClassesTuple
= AliasSeq
!Object
;
4370 else static if (!is(BaseTypeTuple
!T
[0] == Object
) && !is(BaseTypeTuple
!T
[0] == class))
4372 alias BaseClassesTuple
= AliasSeq
!();
4376 alias BaseClassesTuple
=
4377 AliasSeq
!(BaseTypeTuple
!T
[0],
4378 BaseClassesTuple
!(BaseTypeTuple
!T
[0]));
4385 import std
.meta
: AliasSeq
;
4390 static assert(!BaseClassesTuple
!Object
.length
);
4391 static assert(is(BaseClassesTuple
!C1
== AliasSeq
!(Object
)));
4392 static assert(is(BaseClassesTuple
!C2
== AliasSeq
!(C1
, Object
)));
4393 static assert(is(BaseClassesTuple
!C3
== AliasSeq
!(C2
, C1
, Object
)));
4396 // https://issues.dlang.org/show_bug.cgi?id=17276
4399 extern (C
++) static interface Ext
4404 extern (C
++) static class E
: Ext
4409 alias BaseClassesWithNoObject
= BaseClassesTuple
!E
;
4415 static assert(!__traits(compiles
, BaseClassesTuple
!S
));
4417 static assert(!__traits(compiles
, BaseClassesTuple
!I
));
4419 class C5
: C4
, I
{ }
4420 static assert(is(BaseClassesTuple
!C5
== AliasSeq
!(C4
, Object
)));
4425 T = The `class` or `interface` to search.
4428 $(REF AliasSeq,std,meta) of all interfaces directly or
4429 indirectly inherited by this class or interface. Interfaces
4430 do not repeat if multiply implemented.
4432 `InterfacesTuple!Object` yields an empty `AliasSeq`.
4434 template InterfacesTuple(T
)
4436 import std
.meta
: NoDuplicates
;
4437 template Flatten(H
, T
...)
4439 static if (T
.length
)
4441 alias Flatten
= AliasSeq
!(Flatten
!H
, Flatten
!T
);
4445 static if (is(H
== interface))
4446 alias Flatten
= AliasSeq
!(H
, InterfacesTuple
!H
);
4448 alias Flatten
= InterfacesTuple
!H
;
4452 static if (is(T S
== super) && S
.length
)
4453 alias InterfacesTuple
= NoDuplicates
!(Flatten
!S
);
4455 alias InterfacesTuple
= AliasSeq
!();
4467 alias TL
= InterfacesTuple
!C
;
4468 static assert(is(TL
[0] == I1
) && is(TL
[1] == I2
));
4477 interface Ia
: Iaa
, Iab
{}
4478 interface Ib
: Iba
, Ibb
{}
4479 interface I
: Ia
, Ib
{}
4482 class C2
: B2
, Ia
, Ib
{}
4483 static assert(is(InterfacesTuple
!I
==
4484 AliasSeq
!(Ia
, Iaa
, Iab
, Ib
, Iba
, Ibb
)));
4485 static assert(is(InterfacesTuple
!C2
==
4486 AliasSeq
!(J
, Ia
, Iaa
, Iab
, Ib
, Iba
, Ibb
)));
4491 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM
4492 * T), in decreasing order, followed by $(D_PARAM T)'s
4493 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
4496 alias TransitiveBaseTypeTuple(T
) = AliasSeq
!(BaseClassesTuple
!T
, InterfacesTuple
!T
);
4504 class B2
: B1
, J1
, J2
{}
4505 class B3
: B2
, J1
{}
4506 alias TL
= TransitiveBaseTypeTuple
!B3
;
4507 assert(TL
.length
== 5);
4508 assert(is (TL
[0] == B2
));
4509 assert(is (TL
[1] == B1
));
4510 assert(is (TL
[2] == Object
));
4511 assert(is (TL
[3] == J1
));
4512 assert(is (TL
[4] == J2
));
4514 assert(TransitiveBaseTypeTuple
!Object
.length
== 0);
4519 Returns a tuple of non-static functions with the name `name` declared in the
4520 class or interface `C`. Covariant duplicates are shrunk into the most
4523 template MemberFunctionsTuple(C
, string name
)
4524 if (is(C
== class) ||
is(C
== interface))
4526 static if (__traits(hasMember
, C
, name
))
4529 * First, collect all overloads in the class hierarchy.
4531 template CollectOverloads(Node
)
4533 static if (__traits(hasMember
, Node
, name
) && __traits(compiles
, __traits(getMember
, Node
, name
)))
4535 // Get all overloads in sight (not hidden).
4536 alias inSight
= __traits(getVirtualMethods
, Node
, name
);
4538 // And collect all overloads in ancestor classes to reveal hidden
4539 // methods. The result may contain duplicates.
4540 template walkThru(Parents
...)
4542 static if (Parents
.length
> 0)
4543 alias walkThru
= AliasSeq
!(
4544 CollectOverloads
!(Parents
[0]),
4545 walkThru
!(Parents
[1 .. $])
4548 alias walkThru
= AliasSeq
!();
4551 static if (is(Node Parents
== super))
4552 alias CollectOverloads
= AliasSeq
!(inSight
, walkThru
!Parents
);
4554 alias CollectOverloads
= AliasSeq
!inSight
;
4557 alias CollectOverloads
= AliasSeq
!(); // no overloads in this hierarchy
4560 static if (name
== "__ctor" || name
== "__dtor")
4561 alias overloads
= AliasSeq
!(__traits(getOverloads
, C
, name
));
4563 // duplicates in this tuple will be removed by shrink()
4564 alias overloads
= CollectOverloads
!C
;
4566 // shrinkOne!args[0] = the most derived one in the covariant siblings of target
4567 // shrinkOne!args[1..$] = non-covariant others
4568 template shrinkOne(/+ alias target, rest... +/ args
...)
4570 import std
.meta
: AliasSeq
;
4571 alias target
= args
[0 .. 1]; // prevent property functions from being evaluated
4572 alias rest
= args
[1 .. $];
4574 static if (rest
.length
> 0)
4576 alias Target
= FunctionTypeOf
!target
;
4577 alias Rest0
= FunctionTypeOf
!(rest
[0]);
4579 static if (isCovariantWith
!(Target
, Rest0
) && isCovariantWith
!(Rest0
, Target
))
4581 // One of these overrides the other. Choose the one from the most derived parent.
4582 static if (is(__traits(parent
, target
) : __traits(parent
, rest
[0])))
4583 alias shrinkOne
= shrinkOne
!(target
, rest
[1 .. $]);
4585 alias shrinkOne
= shrinkOne
!(rest
[0], rest
[1 .. $]);
4587 else static if (isCovariantWith
!(Target
, Rest0
))
4588 // target overrides rest[0] -- erase rest[0].
4589 alias shrinkOne
= shrinkOne
!(target
, rest
[1 .. $]);
4590 else static if (isCovariantWith
!(Rest0
, Target
))
4591 // rest[0] overrides target -- erase target.
4592 alias shrinkOne
= shrinkOne
!(rest
[0], rest
[1 .. $]);
4594 // target and rest[0] are distinct.
4595 alias shrinkOne
= AliasSeq
!(
4596 shrinkOne
!(target
, rest
[1 .. $]),
4601 alias shrinkOne
= AliasSeq
!target
; // done
4605 * Now shrink covariant overloads into one.
4607 template shrink(overloads
...)
4609 static if (overloads
.length
> 0)
4611 alias temp
= shrinkOne
!overloads
;
4612 alias shrink
= AliasSeq
!(temp
[0], shrink
!(temp
[1 .. $]));
4615 alias shrink
= AliasSeq
!(); // done
4619 alias MemberFunctionsTuple
= shrink
!overloads
;
4622 alias MemberFunctionsTuple
= AliasSeq
!();
4628 interface I
{ I
foo(); }
4631 real foo(real v
) { return v
; }
4635 override C
foo() { return this; } // covariant overriding of I.foo()
4637 alias foos
= MemberFunctionsTuple
!(C
, "foo");
4638 static assert(foos
.length
== 2);
4639 static assert(__traits(isSame
, foos
[0], C
.foo
));
4640 static assert(__traits(isSame
, foos
[1], B
.foo
));
4643 // https://issues.dlang.org/show_bug.cgi?id=15920
4646 import std
.meta
: AliasSeq
;
4655 override void f(int){}
4657 alias fs
= MemberFunctionsTuple
!(B
, "f");
4658 alias bfs
= __traits(getOverloads
, B
, "f");
4659 assert(__traits(isSame
, fs
[0], bfs
[0]) ||
__traits(isSame
, fs
[0], bfs
[1]));
4660 assert(__traits(isSame
, fs
[1], bfs
[0]) ||
__traits(isSame
, fs
[1], bfs
[1]));
4663 // https://issues.dlang.org/show_bug.cgi?id=8388
4670 this(int i
, float j
) {}
4674 Commented out, because this causes a cyclic dependency
4675 between module constructors/destructors error. Might
4676 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */
4688 alias test_ctor
= MemberFunctionsTuple
!(C
, "__ctor");
4689 assert(test_ctor
.length
== 4);
4690 alias test_dtor
= MemberFunctionsTuple
!(C
, "__dtor");
4691 assert(test_dtor
.length
== 1);
4692 alias test2_ctor
= MemberFunctionsTuple
!(D
, "__ctor");
4693 assert(test2_ctor
.length
== 1);
4694 alias test2_dtor
= MemberFunctionsTuple
!(D
, "__dtor");
4695 assert(test2_dtor
.length
== 1);
4700 interface I
{ I
test(); }
4701 interface J
: I
{ J
test(); }
4702 interface K
{ K
test(int); }
4705 K
test(int) { return this; }
4706 B
test() { return this; }
4707 static void test(string
) { }
4711 override C
test() { return this; }
4713 alias test =MemberFunctionsTuple
!(C
, "test");
4714 static assert(test.length
== 2);
4715 static assert(is(FunctionTypeOf
!(test[0]) == FunctionTypeOf
!(C
.test)));
4716 static assert(is(FunctionTypeOf
!(test[1]) == FunctionTypeOf
!(K
.test)));
4717 alias noexist
= MemberFunctionsTuple
!(C
, "noexist");
4718 static assert(noexist
.length
== 0);
4720 interface L
{ int prop() @property; }
4721 alias prop
= MemberFunctionsTuple
!(L
, "prop");
4722 static assert(prop
.length
== 1);
4730 interface Test
: Test_I
{}
4731 alias Test_foo
= MemberFunctionsTuple
!(Test
, "foo");
4732 static assert(Test_foo
.length
== 3);
4733 static assert(is(typeof(&Test_foo
[0]) == void function()));
4734 static assert(is(typeof(&Test_foo
[2]) == void function(int)));
4735 static assert(is(typeof(&Test_foo
[1]) == void function(int, int)));
4740 Returns an alias to the template that `T` is an instance of.
4741 It will return `void` if a symbol without a template is given.
4743 alias TemplateOf(alias T
: Base
!Args
, alias Base
, Args
...) = Base
;
4746 alias TemplateOf(T
: Base
!Args
, alias Base
, Args
...) = Base
;
4749 alias TemplateOf(T
) = void;
4755 static assert(__traits(isSame
, TemplateOf
!(Foo
!(int, real)), Foo
));
4761 template Foo2(A
, B
) {}
4762 template Foo3(alias A
) {}
4763 template Foo4(string A
) {}
4765 struct Foo6(A
, B
) {}
4766 struct Foo7(alias A
) {}
4767 template Foo8(A
) { template Foo9(B
) {} }
4770 static assert(__traits(isSame
, TemplateOf
!(Foo1
!(int)), Foo1
));
4771 static assert(__traits(isSame
, TemplateOf
!(Foo2
!(int, int)), Foo2
));
4772 static assert(__traits(isSame
, TemplateOf
!(Foo3
!(123)), Foo3
));
4773 static assert(__traits(isSame
, TemplateOf
!(Foo4
!("123")), Foo4
));
4774 static assert(__traits(isSame
, TemplateOf
!(Foo5
!(int)), Foo5
));
4775 static assert(__traits(isSame
, TemplateOf
!(Foo6
!(int, int)), Foo6
));
4776 static assert(__traits(isSame
, TemplateOf
!(Foo7
!(123)), Foo7
));
4777 static assert(__traits(isSame
, TemplateOf
!(Foo8
!(int).Foo9
!(real)), Foo8
!(int).Foo9
));
4778 static assert(__traits(isSame
, TemplateOf
!(Foo10
!()), Foo10
));
4781 // https://issues.dlang.org/show_bug.cgi?id=18214
4784 static assert(is(TemplateOf
!(int[]) == void));
4785 static assert(is(TemplateOf
!bool == void));
4789 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4791 alias TemplateArgsOf(alias T
: Base
!Args
, alias Base
, Args
...) = Args
;
4794 alias TemplateArgsOf(T
: Base
!Args
, alias Base
, Args
...) = Args
;
4799 import std
.meta
: AliasSeq
;
4802 static assert(is(TemplateArgsOf
!(Foo
!(int, real)) == AliasSeq
!(int, real)));
4808 template Foo2(A
, B
) {}
4809 template Foo3(alias A
) {}
4810 template Foo4(string A
) {}
4812 struct Foo6(A
, B
) {}
4813 struct Foo7(alias A
) {}
4814 template Foo8(A
) { template Foo9(B
) {} }
4819 static assert(is(TemplateArgsOf
!(Foo1
!(int)) == AliasSeq
!(int)));
4820 static assert(is(TemplateArgsOf
!(Foo2
!(int, int)) == AliasSeq
!(int, int)));
4821 static assert(__traits(isSame
, TemplateArgsOf
!(Foo3
!(x
)), AliasSeq
!(x
)));
4822 static assert(TemplateArgsOf
!(Foo4
!(y
)) == AliasSeq
!(y
));
4823 static assert(is(TemplateArgsOf
!(Foo5
!(int)) == AliasSeq
!(int)));
4824 static assert(is(TemplateArgsOf
!(Foo6
!(int, int)) == AliasSeq
!(int, int)));
4825 static assert(__traits(isSame
, TemplateArgsOf
!(Foo7
!(x
)), AliasSeq
!(x
)));
4826 static assert(is(TemplateArgsOf
!(Foo8
!(int).Foo9
!(real)) == AliasSeq
!(real)));
4827 static assert(is(TemplateArgsOf
!(Foo10
!()) == AliasSeq
!()));
4830 // Returns the largest alignment in a type tuple.
4831 package enum maxAlignment(U
...) =
4833 size_t result
= U
[0].alignof
;
4834 static foreach (T
; U
[1 .. $])
4835 if (result
< T
.alignof
)
4841 Returns class instance alignment.
4843 template classInstanceAlignment(T
)
4846 enum classInstanceAlignment
= __traits(classInstanceAlignment
, T
);
4855 // As class instance always has a hidden pointer
4856 static assert(classInstanceAlignment
!A
== (void*).alignof
);
4857 static assert(classInstanceAlignment
!B
== long.alignof
);
4861 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4863 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4866 Get the type that all types can be implicitly converted to. Useful
4867 e.g. in figuring out an array type from a bunch of initializing
4868 values. Returns $(D_PARAM void) if passed an empty list, or if the
4869 types have no common type.
4871 template CommonType(T
...)
4873 static if (T
.length
== 1)
4874 alias CommonType
= typeof(T
[0].init
);
4875 else static if (is(typeof(true ? T
[0].init
: T
[1].init
) U
))
4876 alias CommonType
= CommonType
!(U
, T
[2 .. $]);
4878 alias CommonType
= void;
4884 alias X
= CommonType
!(int, long, short);
4885 assert(is(X
== long));
4886 alias Y
= CommonType
!(int, char[], short);
4887 assert(is(Y
== void));
4893 static assert(is(CommonType
!(3) == int));
4894 static assert(is(CommonType
!(double, 4, float) == double));
4895 static assert(is(CommonType
!(string
, char[]) == const(char)[]));
4896 static assert(is(CommonType
!(3, 3U) == uint));
4897 static assert(is(CommonType
!(double, int) == double));
4903 T = The type to check
4906 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4909 If `T` is a class derived from `Object`, the result of
4910 $(LREF TransitiveBaseTypeTuple) is returned.
4912 If the type is not a built-in value type or a class derived from
4913 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4916 $(LREF isImplicitlyConvertible)
4918 template AllImplicitConversionTargets(T
)
4920 static if (is(T
== bool))
4921 alias AllImplicitConversionTargets
=
4922 AliasSeq
!(byte, AllImplicitConversionTargets
!byte);
4923 else static if (is(T
== byte))
4924 alias AllImplicitConversionTargets
=
4925 AliasSeq
!(char, ubyte, short, AllImplicitConversionTargets
!short);
4926 else static if (is(T
== ubyte))
4927 alias AllImplicitConversionTargets
=
4928 AliasSeq
!(byte, char, short, AllImplicitConversionTargets
!short);
4929 else static if (is(T
== short))
4930 alias AllImplicitConversionTargets
=
4931 AliasSeq
!(ushort, wchar, int, AllImplicitConversionTargets
!int);
4932 else static if (is(T
== ushort))
4933 alias AllImplicitConversionTargets
=
4934 AliasSeq
!(short, wchar, dchar, AllImplicitConversionTargets
!dchar);
4935 else static if (is(T
== int))
4936 alias AllImplicitConversionTargets
=
4937 AliasSeq
!(dchar, uint, long, AllImplicitConversionTargets
!long);
4938 else static if (is(T
== uint))
4939 alias AllImplicitConversionTargets
=
4940 AliasSeq
!(dchar, int, long, AllImplicitConversionTargets
!long);
4941 else static if (is(T
== long))
4942 alias AllImplicitConversionTargets
= AliasSeq
!(ulong, CentTypeList
, float, double, real);
4943 else static if (is(T
== ulong))
4944 alias AllImplicitConversionTargets
= AliasSeq
!(long, CentTypeList
, float, double, real);
4945 else static if (is(T
== float))
4946 alias AllImplicitConversionTargets
= AliasSeq
!(double, real);
4947 else static if (is(T
== double))
4948 alias AllImplicitConversionTargets
= AliasSeq
!(float, real);
4949 else static if (is(T
== real))
4950 alias AllImplicitConversionTargets
= AliasSeq
!(float, double);
4951 else static if (is(T
== char))
4952 alias AllImplicitConversionTargets
=
4953 AliasSeq
!(byte, ubyte, short, AllImplicitConversionTargets
!short);
4954 else static if (is(T
== wchar))
4955 alias AllImplicitConversionTargets
=
4956 AliasSeq
!(short, ushort, dchar, AllImplicitConversionTargets
!dchar);
4957 else static if (is(T
== dchar))
4958 alias AllImplicitConversionTargets
=
4959 AliasSeq
!(int, uint, long, AllImplicitConversionTargets
!long);
4960 else static if (is(T
== class))
4961 alias AllImplicitConversionTargets
= staticMap
!(ApplyLeft
!(CopyConstness
, T
), TransitiveBaseTypeTuple
!T
);
4962 else static if (is(T
== interface))
4963 alias AllImplicitConversionTargets
= staticMap
!(ApplyLeft
!(CopyConstness
, T
), InterfacesTuple
!T
);
4964 else static if (isDynamicArray
!T
&& !is(typeof(T
.init
[0]) == const))
4966 static if (is(typeof(T
.init
[0]) == shared))
4967 alias AllImplicitConversionTargets
=
4968 AliasSeq
!(const(shared(Unqual
!(typeof(T
.init
[0]))))[]);
4970 alias AllImplicitConversionTargets
=
4971 AliasSeq
!(const(Unqual
!(typeof(T
.init
[0])))[]);
4973 else static if (is(T
: void*) && !is(T
== void*))
4974 alias AllImplicitConversionTargets
= AliasSeq
!(void*);
4975 else static if (is(cent) && is(T
== cent))
4976 alias AllImplicitConversionTargets
= AliasSeq
!(UnsignedCentTypeList
, float, double, real);
4977 else static if (is(ucent) && is(T
== ucent))
4978 alias AllImplicitConversionTargets
= AliasSeq
!(SignedCentTypeList
, float, double, real);
4980 alias AllImplicitConversionTargets
= AliasSeq
!();
4986 import std
.meta
: AliasSeq
;
4988 static assert(is(AllImplicitConversionTargets
!(ulong) == AliasSeq
!(long, float, double, real)));
4989 static assert(is(AllImplicitConversionTargets
!(int) == AliasSeq
!(dchar, uint, long, ulong, float, double, real)));
4990 static assert(is(AllImplicitConversionTargets
!(float) == AliasSeq
!(double, real)));
4991 static assert(is(AllImplicitConversionTargets
!(double) == AliasSeq
!(float, real)));
4993 static assert(is(AllImplicitConversionTargets
!(char) ==
4994 AliasSeq
!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4995 ulong, float, double, real)
4997 static assert(is(AllImplicitConversionTargets
!(wchar) == AliasSeq
!(
4998 short, ushort, dchar, int, uint, long, ulong, float, double, real
5000 static assert(is(AllImplicitConversionTargets
!(dchar) == AliasSeq
!(
5001 int, uint, long, ulong, float, double, real
5004 static assert(is(AllImplicitConversionTargets
!(string
) == AliasSeq
!(const(char)[])));
5005 static assert(is(AllImplicitConversionTargets
!(int*) == AliasSeq
!(void*)));
5011 static assert(is(AllImplicitConversionTargets
!(C
) == AliasSeq
!(Object
, A
, B
)));
5012 static assert(is(AllImplicitConversionTargets
!(const C
) == AliasSeq
!(const Object
, const A
, const B
)));
5013 static assert(is(AllImplicitConversionTargets
!(immutable C
) == AliasSeq
!(
5014 immutable Object
, immutable A
, immutable B
5017 interface I
: A
, B
{}
5019 static assert(is(AllImplicitConversionTargets
!(I
) == AliasSeq
!(A
, B
)));
5020 static assert(is(AllImplicitConversionTargets
!(const I
) == AliasSeq
!(const A
, const B
)));
5021 static assert(is(AllImplicitConversionTargets
!(immutable I
) == AliasSeq
!(
5022 immutable A
, immutable B
5028 static assert(is(AllImplicitConversionTargets
!(double)[0] == float));
5029 static assert(is(AllImplicitConversionTargets
!(double)[1] == real));
5030 static assert(is(AllImplicitConversionTargets
!(string
)[0] == const(char)[]));
5036 T = The type to check
5039 This template is considered out-dated. It will be removed from
5040 Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5043 An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5046 If `T` is a class derived from `Object`, the result of
5047 $(LREF TransitiveBaseTypeTuple) is returned.
5049 If the type is not a built-in value type or a class derived from
5050 `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5053 The possible targets are computed more conservatively than the
5054 language allows, eliminating all dangerous conversions. For example,
5055 `ImplicitConversionTargets!double` does not include `float`.
5058 $(LREF isImplicitlyConvertible)
5060 // @@@DEPRECATED_[2.107.0]@@@
5061 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5062 ~ "and will be removed in 2.107.0")
5063 template ImplicitConversionTargets(T
)
5065 static if (is(T
== bool))
5066 alias ImplicitConversionTargets
=
5067 AliasSeq
!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList
,
5068 float, double, real, char, wchar, dchar);
5069 else static if (is(T
== byte))
5070 alias ImplicitConversionTargets
=
5071 AliasSeq
!(short, ushort, int, uint, long, ulong, CentTypeList
,
5072 float, double, real, char, wchar, dchar);
5073 else static if (is(T
== ubyte))
5074 alias ImplicitConversionTargets
=
5075 AliasSeq
!(short, ushort, int, uint, long, ulong, CentTypeList
,
5076 float, double, real, char, wchar, dchar);
5077 else static if (is(T
== short))
5078 alias ImplicitConversionTargets
=
5079 AliasSeq
!(int, uint, long, ulong, CentTypeList
, float, double, real);
5080 else static if (is(T
== ushort))
5081 alias ImplicitConversionTargets
=
5082 AliasSeq
!(int, uint, long, ulong, CentTypeList
, float, double, real);
5083 else static if (is(T
== int))
5084 alias ImplicitConversionTargets
=
5085 AliasSeq
!(long, ulong, CentTypeList
, float, double, real);
5086 else static if (is(T
== uint))
5087 alias ImplicitConversionTargets
=
5088 AliasSeq
!(long, ulong, CentTypeList
, float, double, real);
5089 else static if (is(T
== long))
5090 alias ImplicitConversionTargets
= AliasSeq
!(float, double, real);
5091 else static if (is(T
== ulong))
5092 alias ImplicitConversionTargets
= AliasSeq
!(float, double, real);
5093 else static if (is(cent) && is(T
== cent))
5094 alias ImplicitConversionTargets
= AliasSeq
!(float, double, real);
5095 else static if (is(ucent) && is(T
== ucent))
5096 alias ImplicitConversionTargets
= AliasSeq
!(float, double, real);
5097 else static if (is(T
== float))
5098 alias ImplicitConversionTargets
= AliasSeq
!(double, real);
5099 else static if (is(T
== double))
5100 alias ImplicitConversionTargets
= AliasSeq
!real;
5101 else static if (is(T
== char))
5102 alias ImplicitConversionTargets
=
5103 AliasSeq
!(wchar, dchar, byte, ubyte, short, ushort,
5104 int, uint, long, ulong, CentTypeList
, float, double, real);
5105 else static if (is(T
== wchar))
5106 alias ImplicitConversionTargets
=
5107 AliasSeq
!(dchar, short, ushort, int, uint, long, ulong, CentTypeList
,
5108 float, double, real);
5109 else static if (is(T
== dchar))
5110 alias ImplicitConversionTargets
=
5111 AliasSeq
!(int, uint, long, ulong, CentTypeList
, float, double, real);
5112 else static if (is(T
: typeof(null)))
5113 alias ImplicitConversionTargets
= AliasSeq
!(typeof(null));
5114 else static if (is(T
== class))
5115 alias ImplicitConversionTargets
= staticMap
!(ApplyLeft
!(CopyConstness
, T
), TransitiveBaseTypeTuple
!(T
));
5116 else static if (isDynamicArray
!T
&& !is(typeof(T
.init
[0]) == const))
5118 static if (is(typeof(T
.init
[0]) == shared))
5119 alias ImplicitConversionTargets
=
5120 AliasSeq
!(const(shared(Unqual
!(typeof(T
.init
[0]))))[]);
5122 alias ImplicitConversionTargets
=
5123 AliasSeq
!(const(Unqual
!(typeof(T
.init
[0])))[]);
5125 else static if (is(T
: void*))
5126 alias ImplicitConversionTargets
= AliasSeq
!(void*);
5128 alias ImplicitConversionTargets
= AliasSeq
!();
5131 deprecated @safe unittest
5133 import std
.meta
: AliasSeq
;
5135 static assert(is(ImplicitConversionTargets
!(ulong) == AliasSeq
!(float, double, real)));
5136 static assert(is(ImplicitConversionTargets
!(int) == AliasSeq
!(long, ulong, float, double, real)));
5137 static assert(is(ImplicitConversionTargets
!(float) == AliasSeq
!(double, real)));
5138 static assert(is(ImplicitConversionTargets
!(double) == AliasSeq
!(real)));
5140 static assert(is(ImplicitConversionTargets
!(char) == AliasSeq
!(
5141 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5143 static assert(is(ImplicitConversionTargets
!(wchar) == AliasSeq
!(
5144 dchar, short, ushort, int, uint, long, ulong, float, double, real
5146 static assert(is(ImplicitConversionTargets
!(dchar) == AliasSeq
!(
5147 int, uint, long, ulong, float, double, real
5150 static assert(is(ImplicitConversionTargets
!(string
) == AliasSeq
!(const(char)[])));
5151 static assert(is(ImplicitConversionTargets
!(void*) == AliasSeq
!(void*)));
5157 static assert(is(ImplicitConversionTargets
!(C
) == AliasSeq
!(Object
, A
, B
)));
5158 static assert(is(ImplicitConversionTargets
!(const C
) == AliasSeq
!(const Object
, const A
, const B
)));
5159 static assert(is(ImplicitConversionTargets
!(immutable C
) == AliasSeq
!(
5160 immutable Object
, immutable A
, immutable B
5164 deprecated @safe unittest
5166 static assert(is(ImplicitConversionTargets
!(double)[0] == real));
5167 static assert(is(ImplicitConversionTargets
!(string
)[0] == const(char)[]));
5171 Is `From` implicitly convertible to `To`?
5173 enum bool isImplicitlyConvertible(From
, To
) = is(From
: To
);
5178 static assert( isImplicitlyConvertible
!(immutable(char), char));
5179 static assert( isImplicitlyConvertible
!(const(char), char));
5180 static assert( isImplicitlyConvertible
!(char, wchar));
5181 static assert(!isImplicitlyConvertible
!(wchar, char));
5183 static assert(!isImplicitlyConvertible
!(const(ushort), ubyte));
5184 static assert(!isImplicitlyConvertible
!(const(uint), ubyte));
5185 static assert(!isImplicitlyConvertible
!(const(ulong), ubyte));
5187 static assert(!isImplicitlyConvertible
!(const(char)[], string
));
5188 static assert( isImplicitlyConvertible
!(string
, const(char)[]));
5192 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5195 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5197 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5199 enum isAssignable(Lhs
, Rhs
= Lhs
) = isRvalueAssignable
!(Lhs
, Rhs
) && isLvalueAssignable
!(Lhs
, Rhs
);
5204 static assert( isAssignable
!(long, int));
5205 static assert(!isAssignable
!(int, long));
5206 static assert( isAssignable
!(const(char)[], string
));
5207 static assert(!isAssignable
!(string
, char[]));
5209 // int is assignable to int
5210 static assert( isAssignable
!int);
5212 // immutable int is not assignable to immutable int
5213 static assert(!isAssignable
!(immutable int));
5217 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5220 enum isRvalueAssignable(Lhs
, Rhs
= Lhs
) = __traits(compiles
, { lvalueOf
!Lhs
= rvalueOf
!Rhs
; });
5232 void opAssign(ref S2
);
5235 static assert( isRvalueAssignable
!(long, int));
5236 static assert(!isRvalueAssignable
!(int, long));
5237 static assert( isRvalueAssignable
!S1
);
5238 static assert(!isRvalueAssignable
!S2
);
5242 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5245 enum isLvalueAssignable(Lhs
, Rhs
= Lhs
) = __traits(compiles
, { lvalueOf
!Lhs
= lvalueOf
!Rhs
; });
5257 void opAssign(ref S2
);
5260 static assert( isLvalueAssignable
!(long, int));
5261 static assert(!isLvalueAssignable
!(int, long));
5262 static assert( isLvalueAssignable
!S1
);
5263 static assert( isLvalueAssignable
!S2
);
5268 static assert(!isAssignable
!(immutable int, int));
5269 static assert( isAssignable
!(int, immutable int));
5271 static assert(!isAssignable
!(inout int, int));
5272 static assert( isAssignable
!(int, inout int));
5273 static assert(!isAssignable
!(inout int));
5275 static assert( isAssignable
!(shared int, int));
5276 static assert( isAssignable
!(int, shared int));
5277 static assert( isAssignable
!(shared int));
5279 static assert( isAssignable
!(void[1], void[1]));
5281 struct S
{ @disable this(); this(int n
){} }
5282 static assert( isAssignable
!(S
, S
));
5284 struct S2
{ this(int n
){} }
5285 static assert( isAssignable
!(S2
, S2
));
5286 static assert(!isAssignable
!(S2
, int));
5288 struct S3
{ @disable void opAssign(); }
5289 static assert( isAssignable
!(S3
, S3
));
5291 struct S3X
{ @disable void opAssign(S3X
); }
5292 static assert(!isAssignable
!(S3X
, S3X
));
5294 struct S4
{ void opAssign(int); }
5295 static assert( isAssignable
!(S4
, S4
));
5296 static assert( isAssignable
!(S4
, int));
5297 static assert( isAssignable
!(S4
, immutable int));
5299 struct S5
{ @disable this(); @disable this(this); }
5300 // https://issues.dlang.org/show_bug.cgi?id=21210
5301 static assert(!isAssignable
!S5
);
5303 // `-preview=in` is enabled
5304 alias DScannerBug895
= int[256];
5305 static if (((in DScannerBug895 a
) { return __traits(isRef
, a
); })(DScannerBug895
.init
))
5307 struct S6
{ void opAssign(in S5
); }
5309 static assert(isRvalueAssignable
!(S6
, S5
));
5310 static assert(isLvalueAssignable
!(S6
, S5
));
5311 static assert(isAssignable
!(S6
, S5
));
5312 static assert(isAssignable
!(S6
, immutable S5
));
5316 mixin(q
{ struct S6
{ void opAssign(in ref S5
); } });
5318 static assert(!isRvalueAssignable
!(S6
, S5
));
5319 static assert( isLvalueAssignable
!(S6
, S5
));
5320 static assert(!isAssignable
!(S6
, S5
));
5321 static assert( isLvalueAssignable
!(S6
, immutable S5
));
5326 // Equivalent with TypeStruct::isAssignable in compiler code.
5327 package template isBlitAssignable(T
)
5329 static if (is(T
== enum))
5331 enum isBlitAssignable
= isBlitAssignable
!(OriginalType
!T
);
5333 else static if (isStaticArray
!T
&& is(T
== E
[n
], E
, size_t n
))
5334 // Workaround for issue 11499 : isStaticArray!T should not be necessary.
5336 enum isBlitAssignable
= isBlitAssignable
!E
;
5338 else static if (is(T
== struct) ||
is(T
== union))
5340 enum isBlitAssignable
= isMutable
!T
&&
5343 bool assignable
= true;
5344 foreach (i
, F
; FieldTypeTuple
!T
)
5351 if (T
.tupleof
[i
].offsetof
== offset
)
5362 assignable
= isBlitAssignable
!(typeof(T
.tupleof
[i
]));
5363 offset
= T
.tupleof
[i
].offsetof
;
5369 enum isBlitAssignable
= isMutable
!T
;
5374 static assert( isBlitAssignable
!int);
5375 static assert(!isBlitAssignable
!(const int));
5377 class C
{ const int i
; }
5378 static assert( isBlitAssignable
!C
);
5381 struct S2
{ const int i
; }
5382 static assert( isBlitAssignable
!S1
);
5383 static assert(!isBlitAssignable
!S2
);
5385 struct S3X
{ union { int x
; int y
; } }
5386 struct S3Y
{ union { int x
; const int y
; } }
5387 struct S3Z
{ union { const int x
; const int y
; } }
5388 static assert( isBlitAssignable
!(S3X
));
5389 static assert( isBlitAssignable
!(S3Y
));
5390 static assert(!isBlitAssignable
!(S3Z
));
5391 static assert(!isBlitAssignable
!(const S3X
));
5392 static assert(!isBlitAssignable
!(inout S3Y
));
5393 static assert(!isBlitAssignable
!(immutable S3Z
));
5394 static assert( isBlitAssignable
!(S3X
[3]));
5395 static assert( isBlitAssignable
!(S3Y
[3]));
5396 static assert(!isBlitAssignable
!(S3Z
[3]));
5397 enum ES3X
: S3X
{ a
= S3X() }
5398 enum ES3Y
: S3Y
{ a
= S3Y() }
5399 enum ES3Z
: S3Z
{ a
= S3Z() }
5400 static assert( isBlitAssignable
!(ES3X
));
5401 static assert( isBlitAssignable
!(ES3Y
));
5402 static assert(!isBlitAssignable
!(ES3Z
));
5403 static assert(!isBlitAssignable
!(const ES3X
));
5404 static assert(!isBlitAssignable
!(inout ES3Y
));
5405 static assert(!isBlitAssignable
!(immutable ES3Z
));
5406 static assert( isBlitAssignable
!(ES3X
[3]));
5407 static assert( isBlitAssignable
!(ES3Y
[3]));
5408 static assert(!isBlitAssignable
!(ES3Z
[3]));
5410 union U1X
{ int x
; int y
; }
5411 union U1Y
{ int x
; const int y
; }
5412 union U1Z
{ const int x
; const int y
; }
5413 static assert( isBlitAssignable
!(U1X
));
5414 static assert( isBlitAssignable
!(U1Y
));
5415 static assert(!isBlitAssignable
!(U1Z
));
5416 static assert(!isBlitAssignable
!(const U1X
));
5417 static assert(!isBlitAssignable
!(inout U1Y
));
5418 static assert(!isBlitAssignable
!(immutable U1Z
));
5419 static assert( isBlitAssignable
!(U1X
[3]));
5420 static assert( isBlitAssignable
!(U1Y
[3]));
5421 static assert(!isBlitAssignable
!(U1Z
[3]));
5422 enum EU1X
: U1X
{ a
= U1X() }
5423 enum EU1Y
: U1Y
{ a
= U1Y() }
5424 enum EU1Z
: U1Z
{ a
= U1Z() }
5425 static assert( isBlitAssignable
!(EU1X
));
5426 static assert( isBlitAssignable
!(EU1Y
));
5427 static assert(!isBlitAssignable
!(EU1Z
));
5428 static assert(!isBlitAssignable
!(const EU1X
));
5429 static assert(!isBlitAssignable
!(inout EU1Y
));
5430 static assert(!isBlitAssignable
!(immutable EU1Z
));
5431 static assert( isBlitAssignable
!(EU1X
[3]));
5432 static assert( isBlitAssignable
!(EU1Y
[3]));
5433 static assert(!isBlitAssignable
!(EU1Z
[3]));
5437 @property int[3] foo() { return [1,2,3]; }
5439 const int x
; // SA is not blit assignable
5441 static assert(!isStaticArray
!SA
);
5442 static assert(!isBlitAssignable
!(SA
[3]));
5447 Works like `isImplicitlyConvertible`, except this cares only about storage
5448 classes of the arguments.
5450 private template isStorageClassImplicitlyConvertible(From
, To
)
5452 alias Pointify(T
) = void*;
5454 enum isStorageClassImplicitlyConvertible
= is(
5455 ModifyTypePreservingTQ
!(Pointify
, From
) :
5456 ModifyTypePreservingTQ
!(Pointify
, To
) );
5461 static assert( isStorageClassImplicitlyConvertible
!( int, const int));
5462 static assert( isStorageClassImplicitlyConvertible
!(immutable int, const int));
5464 static assert(!isStorageClassImplicitlyConvertible
!(const int, int));
5465 static assert(!isStorageClassImplicitlyConvertible
!(const int, immutable int));
5466 static assert(!isStorageClassImplicitlyConvertible
!(int, shared int));
5467 static assert(!isStorageClassImplicitlyConvertible
!(shared int, int));
5472 Determines whether the function type `F` is covariant with `G`, i.e.,
5473 functions of the type `F` can override ones of the type `G`.
5475 template isCovariantWith(F
, G
)
5476 if (is(F
== function) && is(G
== function) ||
5477 is(F
== delegate) && is(G
== delegate) ||
5478 isFunctionPointer
!F
&& isFunctionPointer
!G
)
5480 static if (is(F
: G
))
5481 enum isCovariantWith
= true;
5488 * Check for calling convention: require exact match.
5490 template checkLinkage()
5492 enum ok
= functionLinkage
!Upr
== functionLinkage
!Lwr
;
5495 * Check for variadic parameter: require exact match.
5497 template checkVariadicity()
5499 enum ok
= variadicFunctionStyle
!Upr
== variadicFunctionStyle
!Lwr
;
5502 * Check for function storage class:
5503 * - overrider can have narrower storage class than base
5507 // Note the order of arguments. The convertion order Lwr -> Upr is
5508 // correct since Upr should be semantically 'narrower' than Lwr.
5509 enum ok
= isStorageClassImplicitlyConvertible
!(Lwr
, Upr
);
5512 * Check for function attributes:
5513 * - require exact match for ref and @property
5514 * - overrider can add pure and nothrow, but can't remove them
5515 * - @safe and @trusted are covariant with each other, unremovable
5517 template checkAttributes()
5519 alias FA
= FunctionAttribute
;
5520 enum uprAtts
= functionAttributes
!Upr
;
5521 enum lwrAtts
= functionAttributes
!Lwr
;
5523 enum wantExact
= FA
.ref_ | FA
.property
;
5524 enum safety
= FA
.safe | FA
.trusted
;
5526 ( (uprAtts
& wantExact
) == (lwrAtts
& wantExact
)) &&
5527 ( (uprAtts
& FA
.pure_
) >= (lwrAtts
& FA
.pure_
)) &&
5528 ( (uprAtts
& FA
.nothrow_
) >= (lwrAtts
& FA
.nothrow_
)) &&
5529 (!!(uprAtts
& safety
) >= !!(lwrAtts
& safety
)) ;
5532 * Check for return type: usual implicit convertion.
5534 template checkReturnType()
5536 enum ok
= is(ReturnType
!Upr
: ReturnType
!Lwr
);
5539 * Check for parameters:
5540 * - require exact match for types
5541 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5542 * - require exact match for in, out, ref and lazy
5543 * - overrider can add scope, but can't remove
5545 template checkParameters()
5547 alias STC
= ParameterStorageClass
;
5548 alias UprParams
= Parameters
!Upr
;
5549 alias LwrParams
= Parameters
!Lwr
;
5550 alias UprPSTCs
= ParameterStorageClassTuple
!Upr
;
5551 alias LwrPSTCs
= ParameterStorageClassTuple
!Lwr
;
5553 template checkNext(size_t i
)
5555 static if (i
< UprParams
.length
)
5557 enum uprStc
= UprPSTCs
[i
];
5558 enum lwrStc
= LwrPSTCs
[i
];
5560 enum wantExact
= STC
.out_ | STC
.ref_ | STC
.lazy_ | STC
.return_
;
5562 ((uprStc
& wantExact
) == (lwrStc
& wantExact
)) &&
5563 ((uprStc
& STC
.scope_
) >= (lwrStc
& STC
.scope_
)) &&
5564 checkNext
!(i
+ 1).ok
;
5567 enum ok
= true; // done
5569 static if (UprParams
.length
== LwrParams
.length
)
5570 enum ok
= is(UprParams
== LwrParams
) && checkNext
!(0).ok
;
5575 /* run all the checks */
5576 enum isCovariantWith
=
5577 checkLinkage
!().ok
&&
5578 checkVariadicity
!().ok
&&
5580 checkAttributes
!().ok
&&
5581 checkReturnType
!().ok
&&
5582 checkParameters
!().ok
;
5589 interface I
{ I
clone(); }
5590 interface J
{ J
clone(); }
5593 override C
clone() // covariant overriding of I.clone()
5599 // C.clone() can override I.clone(), indeed.
5600 static assert(isCovariantWith
!(typeof(C
.clone
), typeof(I
.clone
)));
5602 // C.clone() can't override J.clone(); the return type C is not implicitly
5603 // convertible to J.
5604 static assert(!isCovariantWith
!(typeof(C
.clone
), typeof(J
.clone
)));
5609 enum bool isCovariantWith(alias f
, alias g
) = .isCovariantWith
!(typeof(f
), typeof(g
));
5611 // covariant return type
5614 interface BaseA
{ const(I
) test(int); }
5615 interface DerivA_1
: BaseA
{ override const(J
) test(int); }
5616 interface DerivA_2
: BaseA
{ override J
test(int); }
5617 static assert( isCovariantWith
!(DerivA_1
.test, BaseA
.test));
5618 static assert( isCovariantWith
!(DerivA_2
.test, BaseA
.test));
5619 static assert(!isCovariantWith
!(BaseA
.test, DerivA_1
.test));
5620 static assert(!isCovariantWith
!(BaseA
.test, DerivA_2
.test));
5621 static assert( isCovariantWith
!(BaseA
.test, BaseA
.test));
5622 static assert( isCovariantWith
!(DerivA_1
.test, DerivA_1
.test));
5623 static assert( isCovariantWith
!(DerivA_2
.test, DerivA_2
.test));
5625 // function, function pointer and delegate
5626 J
function() derived_function
;
5627 I
function() base_function
;
5628 J
delegate() derived_delegate
;
5629 I
delegate() base_delegate
;
5630 static assert(.isCovariantWith
!(typeof(derived_function
), typeof(base_function
)));
5631 static assert(.isCovariantWith
!(typeof(*derived_function
), typeof(*base_function
)));
5632 static assert(.isCovariantWith
!(typeof(derived_delegate
), typeof(base_delegate
)));
5635 interface BaseB
{ void test( int*, int*); }
5636 interface DerivB_1
: BaseB
{ override void test(scope int*, int*); }
5637 interface DerivB_2
: BaseB
{ override void test( int*, scope int*); }
5638 interface DerivB_3
: BaseB
{ override void test(scope int*, scope int*); }
5639 static assert( isCovariantWith
!(DerivB_1
.test, BaseB
.test));
5640 static assert( isCovariantWith
!(DerivB_2
.test, BaseB
.test));
5641 static assert( isCovariantWith
!(DerivB_3
.test, BaseB
.test));
5642 static assert(!isCovariantWith
!(BaseB
.test, DerivB_1
.test));
5643 static assert(!isCovariantWith
!(BaseB
.test, DerivB_2
.test));
5644 static assert(!isCovariantWith
!(BaseB
.test, DerivB_3
.test));
5646 // function storage class
5647 interface BaseC
{ void test() ; }
5648 interface DerivC_1
: BaseC
{ override void test() const; }
5649 static assert( isCovariantWith
!(DerivC_1
.test, BaseC
.test));
5650 static assert(!isCovariantWith
!(BaseC
.test, DerivC_1
.test));
5652 // increasing safety
5653 interface BaseE
{ void test() ; }
5654 interface DerivE_1
: BaseE
{ override void test() @safe ; }
5655 interface DerivE_2
: BaseE
{ override void test() @trusted; }
5656 static assert( isCovariantWith
!(DerivE_1
.test, BaseE
.test));
5657 static assert( isCovariantWith
!(DerivE_2
.test, BaseE
.test));
5658 static assert(!isCovariantWith
!(BaseE
.test, DerivE_1
.test));
5659 static assert(!isCovariantWith
!(BaseE
.test, DerivE_2
.test));
5661 // @safe and @trusted
5665 void test2() @trusted;
5667 interface DerivF
: BaseF
5669 override void test1() @trusted;
5670 override void test2() @safe;
5672 static assert( isCovariantWith
!(DerivF
.test1
, BaseF
.test1
));
5673 static assert( isCovariantWith
!(DerivF
.test2
, BaseF
.test2
));
5677 // Needed for rvalueOf/lvalueOf because "inout on return means
5678 // inout must be on a parameter as well"
5679 private struct __InoutWorkaroundStruct
{}
5682 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5683 `__traits(compiles, ...)` purposes. No actual value is returned.
5686 T = The type to transform
5688 Note: Trying to use returned value will result in a
5689 "Symbol Undefined" error at link time.
5691 @property T
rvalueOf(T
)(inout __InoutWorkaroundStruct
= __InoutWorkaroundStruct
.init
);
5694 @property ref T
lvalueOf(T
)(inout __InoutWorkaroundStruct
= __InoutWorkaroundStruct
.init
);
5696 // Note: can't put these unittests together as function overloads
5697 // aren't allowed inside functions.
5702 static assert(is(typeof(f(rvalueOf
!int)) == int));
5708 static bool f(ref int);
5709 static assert(is(typeof(f(lvalueOf
!int)) == bool));
5714 void needLvalue(T
)(ref T
);
5717 struct Nested
{ void f() { ++i
; } }
5718 static foreach (T
; AliasSeq
!(int, immutable int, inout int, string
, S
, Nested
, Object
))
5720 static assert(!__traits(compiles
, needLvalue(rvalueOf
!T
)));
5721 static assert( __traits(compiles
, needLvalue(lvalueOf
!T
)));
5722 static assert(is(typeof(rvalueOf
!T
) == T
));
5723 static assert(is(typeof(lvalueOf
!T
) == T
));
5726 static assert(!__traits(compiles
, rvalueOf
!int = 1));
5727 static assert( __traits(compiles
, lvalueOf
!byte = 127));
5728 static assert(!__traits(compiles
, lvalueOf
!byte = 128));
5732 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5734 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5738 template BooleanTypeOf(T
)
5740 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
5741 alias X
= BooleanTypeOf
!AT
;
5743 alias X
= OriginalType
!T
;
5745 static if (is(immutable X
== immutable bool))
5747 alias BooleanTypeOf
= X
;
5750 static assert(0, T
.stringof
~" is not boolean type");
5755 // unexpected failure, maybe dmd type-merging bug
5756 static foreach (T
; AliasSeq
!bool)
5757 static foreach (Q
; TypeQualifierList
)
5759 static assert( is(Q
!T
== BooleanTypeOf
!( Q
!T
)));
5760 static assert( is(Q
!T
== BooleanTypeOf
!( SubTypeOf
!(Q
!T
) )));
5763 static foreach (T
; AliasSeq
!(void, NumericTypeList
, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList
))
5764 static foreach (Q
; TypeQualifierList
)
5766 static assert(!is(BooleanTypeOf
!( Q
!T
)), Q
!T
.stringof
);
5767 static assert(!is(BooleanTypeOf
!( SubTypeOf
!(Q
!T
) )));
5783 static assert(is(BooleanTypeOf
!B
== bool));
5784 static assert(is(BooleanTypeOf
!S
== bool));
5789 template IntegralTypeOf(T
)
5791 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
5792 alias X
= IntegralTypeOf
!AT
;
5794 alias X
= OriginalType
!T
;
5796 static if (__traits(isIntegral
, X
) && __traits(isZeroInit
, X
) // Not char, wchar, or dchar.
5797 && !is(immutable X
== immutable bool) && !is(X
== __vector
))
5799 alias IntegralTypeOf
= X
;
5802 static assert(0, T
.stringof
~" is not an integral type");
5807 static foreach (T
; IntegralTypeList
)
5808 static foreach (Q
; TypeQualifierList
)
5810 static assert( is(Q
!T
== IntegralTypeOf
!( Q
!T
)));
5811 static assert( is(Q
!T
== IntegralTypeOf
!( SubTypeOf
!(Q
!T
) )));
5814 static foreach (T
; AliasSeq
!(void, bool, FloatingPointTypeList
,
5815 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList
))
5816 static foreach (Q
; TypeQualifierList
)
5818 static assert(!is(IntegralTypeOf
!( Q
!T
)));
5819 static assert(!is(IntegralTypeOf
!( SubTypeOf
!(Q
!T
) )));
5825 template FloatingPointTypeOf(T
)
5827 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
5828 alias X
= FloatingPointTypeOf
!AT
;
5830 alias X
= OriginalType
!T
;
5832 static if (is(immutable X
== immutable U
, U
) && is(U
== float) ||
is(U
== double) ||
is(U
== real))
5834 alias FloatingPointTypeOf
= X
;
5837 static assert(0, T
.stringof
~" is not a floating point type");
5842 static foreach (T
; FloatingPointTypeList
)
5843 static foreach (Q
; TypeQualifierList
)
5845 static assert( is(Q
!T
== FloatingPointTypeOf
!( Q
!T
)));
5846 static assert( is(Q
!T
== FloatingPointTypeOf
!( SubTypeOf
!(Q
!T
) )));
5849 static foreach (T
; AliasSeq
!(void, bool, IntegralTypeList
, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList
))
5850 static foreach (Q
; TypeQualifierList
)
5852 static assert(!is(FloatingPointTypeOf
!( Q
!T
)));
5853 static assert(!is(FloatingPointTypeOf
!( SubTypeOf
!(Q
!T
) )));
5859 template NumericTypeOf(T
)
5861 static if (is(IntegralTypeOf
!T X
) ||
is(FloatingPointTypeOf
!T X
))
5863 alias NumericTypeOf
= X
;
5866 static assert(0, T
.stringof
~" is not a numeric type");
5871 static foreach (T
; NumericTypeList
)
5872 static foreach (Q
; TypeQualifierList
)
5874 static assert( is(Q
!T
== NumericTypeOf
!( Q
!T
)));
5875 static assert( is(Q
!T
== NumericTypeOf
!( SubTypeOf
!(Q
!T
) )));
5878 static foreach (T
; AliasSeq
!(void, bool, CharTypeList
, /*ImaginaryTypeList, ComplexTypeList*/))
5879 static foreach (Q
; TypeQualifierList
)
5881 static assert(!is(NumericTypeOf
!( Q
!T
)));
5882 static assert(!is(NumericTypeOf
!( SubTypeOf
!(Q
!T
) )));
5888 template UnsignedTypeOf(T
)
5890 static if (is(IntegralTypeOf
!T X
) && __traits(isUnsigned
, X
))
5891 alias UnsignedTypeOf
= X
;
5893 static assert(0, T
.stringof
~" is not an unsigned type.");
5898 template SignedTypeOf(T
)
5900 static if (is(IntegralTypeOf
!T X
) && !__traits(isUnsigned
, X
))
5901 alias SignedTypeOf
= X
;
5902 else static if (is(FloatingPointTypeOf
!T X
))
5903 alias SignedTypeOf
= X
;
5905 static assert(0, T
.stringof
~" is not an signed type.");
5910 template CharTypeOf(T
)
5912 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
5913 alias X
= CharTypeOf
!AT
;
5915 alias X
= OriginalType
!T
;
5917 static if (is(immutable X
== immutable U
, U
) && is(U
== char) ||
is(U
== wchar) ||
is(U
== dchar))
5919 alias CharTypeOf
= X
;
5922 static assert(0, T
.stringof
~" is not a character type");
5927 static foreach (T
; CharTypeList
)
5928 static foreach (Q
; TypeQualifierList
)
5930 static assert( is(CharTypeOf
!( Q
!T
)));
5931 static assert( is(CharTypeOf
!( SubTypeOf
!(Q
!T
) )));
5934 static foreach (T
; AliasSeq
!(void, bool, NumericTypeList
, /*ImaginaryTypeList, ComplexTypeList*/))
5935 static foreach (Q
; TypeQualifierList
)
5937 static assert(!is(CharTypeOf
!( Q
!T
)));
5938 static assert(!is(CharTypeOf
!( SubTypeOf
!(Q
!T
) )));
5941 static foreach (T
; AliasSeq
!(string
, wstring
, dstring
, char[4]))
5942 static foreach (Q
; TypeQualifierList
)
5944 static assert(!is(CharTypeOf
!( Q
!T
)));
5945 static assert(!is(CharTypeOf
!( SubTypeOf
!(Q
!T
) )));
5951 template StaticArrayTypeOf(T
)
5953 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
5954 alias X
= StaticArrayTypeOf
!AT
;
5956 alias X
= OriginalType
!T
;
5958 static if (__traits(isStaticArray
, X
))
5959 alias StaticArrayTypeOf
= X
;
5961 static assert(0, T
.stringof
~" is not a static array type");
5966 static foreach (T
; AliasSeq
!(bool, NumericTypeList
, /*ImaginaryTypeList, ComplexTypeList*/))
5967 static foreach (Q
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
5969 static assert(is( Q
!( T
[1] ) == StaticArrayTypeOf
!( Q
!( T
[1] ) ) ));
5971 static foreach (P
; TypeQualifierList
)
5972 { // SubTypeOf cannot have inout type
5973 static assert(is( Q
!(P
!(T
[1])) == StaticArrayTypeOf
!( Q
!(SubTypeOf
!(P
!(T
[1]))) ) ));
5977 static foreach (T
; AliasSeq
!void)
5978 static foreach (Q
; AliasSeq
!TypeQualifierList
)
5980 static assert(is( StaticArrayTypeOf
!( Q
!(void[1]) ) == Q
!(void[1]) ));
5986 template DynamicArrayTypeOf(T
)
5988 import core
.internal
.traits
: _DynamicArrayTypeOf
= DynamicArrayTypeOf
;
5989 alias DynamicArrayTypeOf
= _DynamicArrayTypeOf
!T
;
5994 import std
.meta
: Alias
;
5995 static foreach (T
; AliasSeq
!(/*void, */bool, NumericTypeList
, /*ImaginaryTypeList, ComplexTypeList*/))
5996 static foreach (Q
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
5998 static assert(is( Q
!T
[] == DynamicArrayTypeOf
!( Q
!T
[] ) ));
5999 static assert(is( Q
!(T
[]) == DynamicArrayTypeOf
!( Q
!(T
[]) ) ));
6001 static foreach (P
; AliasSeq
!(Alias
, ConstOf
, ImmutableOf
))
6003 static assert(is( Q
!(P
!T
[]) == DynamicArrayTypeOf
!( Q
!(SubTypeOf
!(P
!T
[])) ) ));
6004 static assert(is( Q
!(P
!(T
[])) == DynamicArrayTypeOf
!( Q
!(SubTypeOf
!(P
!(T
[]))) ) ));
6008 static assert(!is(DynamicArrayTypeOf
!(int[3])));
6009 static assert(!is(DynamicArrayTypeOf
!(void[3])));
6010 static assert(!is(DynamicArrayTypeOf
!(typeof(null))));
6015 template ArrayTypeOf(T
)
6017 static if (is(StaticArrayTypeOf
!T X
) ||
is(DynamicArrayTypeOf
!T X
))
6019 alias ArrayTypeOf
= X
;
6022 static assert(0, T
.stringof
~" is not an array type");
6026 * Converts strings and string-like types to the corresponding dynamic array of characters.
6028 * T = one of the following:
6029 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6030 * (`shared` is rejected)
6031 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6032 * (`shared` is rejected)
6033 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6035 * Other cases are rejected with a compile time error.
6036 * `typeof(null)` is rejected.
6039 * The result of `[]` applied to the qualified character type.
6041 template StringTypeOf(T
)
6043 static if (is(T
== typeof(null)))
6045 // It is impossible to determine exact string type from typeof(null) -
6046 // it means that StringTypeOf!(typeof(null)) is undefined.
6047 // Then this behavior is convenient for template constraint.
6048 static assert(0, T
.stringof
~" is not a string type");
6050 else static if (is(T
: const char[]) ||
is(T
: const wchar[]) ||
is(T
: const dchar[]))
6052 static if (is(T
: U
[], U
))
6053 alias StringTypeOf
= U
[];
6058 static assert(0, T
.stringof
~" is not a string type");
6063 import std
.meta
: Alias
;
6064 static foreach (T
; CharTypeList
)
6065 static foreach (Q
; AliasSeq
!(Alias
, ConstOf
, ImmutableOf
, InoutOf
))
6067 static assert(is(Q
!T
[] == StringTypeOf
!( Q
!T
[] )));
6069 static if (!__traits(isSame
, Q
, InoutOf
))
6071 static assert(is(Q
!T
[] == StringTypeOf
!( SubTypeOf
!(Q
!T
[]) )));
6074 struct C(S
) { S val
; alias val
this; }
6075 static assert(is(StringTypeOf
!(C
!Str
) == Str
));
6079 static foreach (T
; CharTypeList
)
6080 static foreach (Q
; AliasSeq
!(SharedOf
, SharedConstOf
, SharedInoutOf
))
6082 static assert(!is(StringTypeOf
!( Q
!T
[] )));
6088 static assert(is(StringTypeOf
!(char[4]) == char[]));
6102 static assert(is(StringTypeOf
!S
== string
));
6103 static assert(is(StringTypeOf
!T
== string
));
6108 template AssocArrayTypeOf(T
)
6110 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
6111 alias X
= AssocArrayTypeOf
!AT
;
6113 alias X
= OriginalType
!T
;
6115 static if (__traits(isAssociativeArray
, X
))
6117 alias AssocArrayTypeOf
= X
;
6120 static assert(0, T
.stringof
~" is not an associative array type");
6125 static foreach (T
; AliasSeq
!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6126 static foreach (P
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
6127 static foreach (Q
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
6128 static foreach (R
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
6130 static assert(is( P
!(Q
!T
[R
!T
]) == AssocArrayTypeOf
!( P
!(Q
!T
[R
!T
]) ) ));
6133 static foreach (T
; AliasSeq
!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6134 static foreach (O
; AliasSeq
!(TypeQualifierList
, InoutOf
, SharedInoutOf
))
6135 static foreach (P
; AliasSeq
!TypeQualifierList
)
6136 static foreach (Q
; AliasSeq
!TypeQualifierList
)
6137 static foreach (R
; AliasSeq
!TypeQualifierList
)
6139 static assert(is( O
!(P
!(Q
!T
[R
!T
])) == AssocArrayTypeOf
!( O
!(SubTypeOf
!(P
!(Q
!T
[R
!T
]))) ) ));
6145 template BuiltinTypeOf(T
)
6147 static if (is(T
: void))
6148 alias BuiltinTypeOf
= void;
6151 static if (is(typeof(__traits(getMember
, T
.init
, __traits(getAliasThis
, T
)[0])) AT
) && !is(AT
[] == AT
))
6152 alias X
= BuiltinTypeOf
!AT
;
6154 alias X
= OriginalType
!T
;
6155 static if (__traits(isArithmetic
, X
) && !is(X
== __vector
) ||
6156 __traits(isStaticArray
, X
) ||
is(X
== E
[], E
) ||
6157 __traits(isAssociativeArray
, X
) ||
is(X
== typeof(null)))
6158 alias BuiltinTypeOf
= X
;
6164 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6166 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6169 * Detect whether `T` is a built-in boolean type.
6171 enum bool isBoolean(T
) = __traits(isUnsigned
, T
) && is(T
: bool);
6176 static assert( isBoolean
!bool);
6177 enum EB
: bool { a
= true }
6178 static assert( isBoolean
!EB
);
6180 struct SubTypeOfBool
6185 static assert(!isBoolean
!(SubTypeOfBool
));
6195 static assert(!isIntegral
!(S
!bool));
6199 * Detect whether `T` is a built-in integral type. Types `bool`,
6200 * `char`, `wchar`, and `dchar` are not considered integral.
6202 template isIntegral(T
)
6204 static if (!__traits(isIntegral
, T
))
6205 enum isIntegral
= false;
6206 else static if (is(T U
== enum))
6207 enum isIntegral
= isIntegral
!U
;
6209 enum isIntegral
= __traits(isZeroInit
, T
) // Not char, wchar, or dchar.
6210 && !is(immutable T
== immutable bool) && !is(T
== __vector
);
6221 isIntegral
!(const(long)) &&
6222 isIntegral
!(immutable(long))
6231 // types which act as integral values do not pass
6238 static assert(!isIntegral
!S
);
6243 static foreach (T
; IntegralTypeList
)
6245 static foreach (Q
; TypeQualifierList
)
6247 static assert( isIntegral
!(Q
!T
));
6248 static assert(!isIntegral
!(SubTypeOf
!(Q
!T
)));
6252 static assert(!isIntegral
!float);
6254 enum EU
: uint { a
= 0, b
= 1, c
= 2 } // base type is unsigned
6255 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6256 enum EI
: int { a
= -1, b
= 0, c
= 1 }
6257 static assert(isIntegral
!EU
&& isUnsigned
!EU
&& !isSigned
!EU
);
6258 static assert(isIntegral
!EI
&& !isUnsigned
!EI
&& isSigned
!EI
);
6262 * Detect whether `T` is a built-in floating point type.
6264 enum bool isFloatingPoint(T
) = __traits(isFloating
, T
) && is(T
: real);
6270 isFloatingPoint
!float &&
6271 isFloatingPoint
!double &&
6272 isFloatingPoint
!real &&
6273 isFloatingPoint
!(const(real)) &&
6274 isFloatingPoint
!(immutable(real))
6277 static assert(!isFloatingPoint
!int);
6279 // types which act as floating point values do not pass
6286 static assert(!isFloatingPoint
!S
);
6291 enum EF
: real { a
= 1.414, b
= 1.732, c
= 2.236 }
6293 static foreach (T
; AliasSeq
!(FloatingPointTypeList
, EF
))
6295 static foreach (Q
; TypeQualifierList
)
6297 static assert( isFloatingPoint
!(Q
!T
));
6298 static assert(!isFloatingPoint
!(SubTypeOf
!(Q
!T
)));
6301 static foreach (T
; IntegralTypeList
)
6303 static foreach (Q
; TypeQualifierList
)
6305 static assert(!isFloatingPoint
!(Q
!T
));
6308 static if (is(__vector(float[4])))
6310 static assert(!isFloatingPoint
!(__vector(float[4])));
6315 * Detect whether `T` is a built-in numeric type (integral or floating
6318 template isNumeric(T
)
6320 static if (!__traits(isArithmetic
, T
))
6321 enum isNumeric
= false;
6322 else static if (__traits(isFloating
, T
))
6323 enum isNumeric
= is(T
: real); // Not __vector, imaginary, or complex.
6324 else static if (is(T U
== enum))
6325 enum isNumeric
= isNumeric
!U
;
6327 enum isNumeric
= __traits(isZeroInit
, T
) // Not char, wchar, or dchar.
6328 && !is(immutable T
== immutable bool) && !is(T
== __vector
);
6342 isNumeric
!(const(real)) &&
6343 isNumeric
!(immutable(real))
6354 // types which act as numeric values do not pass
6361 static assert(!isNumeric
!S
);
6366 static foreach (T
; AliasSeq
!(NumericTypeList
))
6368 static foreach (Q
; TypeQualifierList
)
6370 static assert( isNumeric
!(Q
!T
));
6371 static assert(!isNumeric
!(SubTypeOf
!(Q
!T
)));
6380 static assert(!isNumeric
!(S
!int));
6382 enum EChar
: char { a
= 0, }
6383 static assert(!isNumeric
!EChar
);
6385 static if (is(__vector(float[4])))
6387 static assert(!isNumeric
!(__vector(float[4])));
6389 static if (is(__vector(int[4])))
6391 static assert(!isNumeric
!(__vector(int[4])));
6394 static assert(!isNumeric
!ifloat);
6395 static assert(!isNumeric
!cfloat);
6399 * Detect whether `T` is a scalar type (a built-in numeric, character or
6402 enum bool isScalarType(T
) = __traits(isScalar
, T
) && is(T
: real);
6407 static assert(!isScalarType
!void);
6408 static assert( isScalarType
!(immutable(byte)));
6409 static assert( isScalarType
!(immutable(ushort)));
6410 static assert( isScalarType
!(immutable(int)));
6411 static assert( isScalarType
!(ulong));
6412 static assert( isScalarType
!(shared(float)));
6413 static assert( isScalarType
!(shared(const bool)));
6414 static assert( isScalarType
!(const(char)));
6415 static assert( isScalarType
!(wchar));
6416 static assert( isScalarType
!(const(dchar)));
6417 static assert( isScalarType
!(const(double)));
6418 static assert( isScalarType
!(const(real)));
6428 static assert(!isScalarType
!(S
!int));
6432 * Detect whether `T` is a basic type (scalar type or void).
6434 enum bool isBasicType(T
) = isScalarType
!T ||
is(immutable T
== immutable void);
6439 static assert(isBasicType
!void);
6440 static assert(isBasicType
!(const(void)));
6441 static assert(isBasicType
!(shared(void)));
6442 static assert(isBasicType
!(immutable(void)));
6443 static assert(isBasicType
!(shared const(void)));
6444 static assert(isBasicType
!(shared inout(void)));
6445 static assert(isBasicType
!(shared inout const(void)));
6446 static assert(isBasicType
!(inout(void)));
6447 static assert(isBasicType
!(inout const(void)));
6448 static assert(isBasicType
!(immutable(int)));
6449 static assert(isBasicType
!(shared(float)));
6450 static assert(isBasicType
!(shared(const bool)));
6451 static assert(isBasicType
!(const(dchar)));
6455 * Detect whether `T` is a built-in unsigned numeric type.
6457 template isUnsigned(T
)
6459 static if (!__traits(isUnsigned
, T
))
6460 enum isUnsigned
= false;
6461 else static if (is(T U
== enum))
6462 enum isUnsigned
= isUnsigned
!U
;
6464 enum isUnsigned
= __traits(isZeroInit
, T
) // Not char, wchar, or dchar.
6465 && !is(immutable T
== immutable bool) && !is(T
== __vector
);
6481 !isUnsigned
!wchar &&
6488 static foreach (T
; AliasSeq
!(UnsignedIntTypeList
))
6490 static foreach (Q
; TypeQualifierList
)
6492 static assert( isUnsigned
!(Q
!T
));
6493 static assert(!isUnsigned
!(SubTypeOf
!(Q
!T
)));
6502 static assert(!isUnsigned
!(S
!uint));
6504 enum EChar
: char { a
= 0, }
6505 static assert(!isUnsigned
!EChar
);
6507 static if (is(__vector(uint[4])))
6509 static assert(!isUnsigned
!(__vector(uint[4])));
6514 * Detect whether `T` is a built-in signed numeric type.
6516 enum bool isSigned(T
) = __traits(isArithmetic
, T
) && !__traits(isUnsigned
, T
)
6536 static assert(isSigned
!E
);
6538 enum Eubyte
: ubyte { e1
= 0 }
6539 static assert(!isSigned
!Eubyte
);
6541 static foreach (T
; AliasSeq
!(SignedIntTypeList
))
6543 static foreach (Q
; TypeQualifierList
)
6545 static assert( isSigned
!(Q
!T
));
6546 static assert(!isSigned
!(SubTypeOf
!(Q
!T
)));
6555 static assert(!isSigned
!(S
!uint));
6557 static if (is(__vector(int[4])))
6559 static assert(!isSigned
!(__vector(int[4])));
6562 static assert(!isSigned
!ifloat);
6563 static assert(!isSigned
!cfloat);
6566 // https://issues.dlang.org/show_bug.cgi?id=17196
6569 static assert(isUnsigned
!bool == false);
6570 static assert(isSigned
!bool == false);
6574 * Detect whether `T` is one of the built-in character types.
6576 * The built-in char types are any of `char`, `wchar` or `dchar`, with
6577 * or without qualifiers.
6579 template isSomeChar(T
)
6581 static if (!__traits(isUnsigned
, T
))
6582 enum isSomeChar
= false;
6583 else static if (is(T U
== enum))
6584 enum isSomeChar
= isSomeChar
!U
;
6586 enum isSomeChar
= !__traits(isZeroInit
, T
);
6593 static assert( isSomeChar
!char);
6594 static assert( isSomeChar
!wchar);
6595 static assert( isSomeChar
!dchar);
6596 static assert( isSomeChar
!(typeof('c')));
6597 static assert( isSomeChar
!(immutable char));
6598 static assert( isSomeChar
!(const dchar));
6601 static assert(!isSomeChar
!int);
6602 static assert(!isSomeChar
!byte);
6603 static assert(!isSomeChar
!string
);
6604 static assert(!isSomeChar
!wstring
);
6605 static assert(!isSomeChar
!dstring
);
6606 static assert(!isSomeChar
!(char[4]));
6611 enum EC
: char { a
= 'x', b
= 'y' }
6613 static foreach (T
; AliasSeq
!(CharTypeList
, EC
))
6615 static foreach (Q
; TypeQualifierList
)
6617 static assert( isSomeChar
!( Q
!T
));
6618 static assert(!isSomeChar
!( SubTypeOf
!(Q
!T
) ));
6622 // alias-this types are not allowed
6628 static assert(!isSomeChar
!(S
!char));
6632 Detect whether `T` is one of the built-in string types.
6634 The built-in string types are `Char[]`, where `Char` is any of `char`,
6635 `wchar` or `dchar`, with or without qualifiers.
6637 Static arrays of characters (like `char[80]`) are not considered
6638 built-in string types.
6640 enum bool isSomeString(T
) = is(immutable T
== immutable C
[], C
) && (is(C
== char) ||
is(C
== wchar) ||
is(C
== dchar));
6646 static assert( isSomeString
!string
);
6647 static assert( isSomeString
!(wchar[]));
6648 static assert( isSomeString
!(dchar[]));
6649 static assert( isSomeString
!(typeof("aaa")));
6650 static assert( isSomeString
!(const(char)[]));
6653 static assert(!isSomeString
!int);
6654 static assert(!isSomeString
!(int[]));
6655 static assert(!isSomeString
!(byte[]));
6656 static assert(!isSomeString
!(typeof(null)));
6657 static assert(!isSomeString
!(char[4]));
6659 enum ES
: string
{ a
= "aaa", b
= "bbb" }
6660 static assert(!isSomeString
!ES
);
6662 static struct Stringish
6667 static assert(!isSomeString
!Stringish
);
6672 static foreach (T
; AliasSeq
!(char[], dchar[], string
, wstring
, dstring
))
6674 static assert( isSomeString
!( T
));
6675 static assert(!isSomeString
!(SubTypeOf
!(T
)));
6677 enum C
: char { _
= 0 }
6678 static assert(!isSomeString
!(C
[]));
6682 * Detect whether type `T` is a narrow string.
6684 * All arrays that use char, wchar, and their qualified versions are narrow
6685 * strings. (Those include string and wstring).
6687 enum bool isNarrowString(T
) = is(immutable T
== immutable C
[], C
) && (is(C
== char) ||
is(C
== wchar));
6692 static assert(isNarrowString
!string
);
6693 static assert(isNarrowString
!wstring
);
6694 static assert(isNarrowString
!(char[]));
6695 static assert(isNarrowString
!(wchar[]));
6697 static assert(!isNarrowString
!dstring
);
6698 static assert(!isNarrowString
!(dchar[]));
6700 static assert(!isNarrowString
!(typeof(null)));
6701 static assert(!isNarrowString
!(char[4]));
6703 enum ES
: string
{ a
= "aaa", b
= "bbb" }
6704 static assert(!isNarrowString
!ES
);
6706 static struct Stringish
6711 static assert(!isNarrowString
!Stringish
);
6716 import std
.meta
: Alias
;
6717 static foreach (T
; AliasSeq
!(char[], string
, wstring
))
6719 static foreach (Q
; AliasSeq
!(Alias
, ConstOf
, ImmutableOf
)/*TypeQualifierList*/)
6721 static assert( isNarrowString
!( Q
!T
));
6722 static assert(!isNarrowString
!( SubTypeOf
!(Q
!T
) ));
6726 static foreach (T
; AliasSeq
!(int, int[], byte[], dchar[], dstring
, char[4]))
6728 static foreach (Q
; TypeQualifierList
)
6730 static assert(!isNarrowString
!( Q
!T
));
6731 static assert(!isNarrowString
!( SubTypeOf
!(Q
!T
) ));
6734 enum C
: char { _
= 0 }
6735 static assert(!isNarrowString
!(C
[]));
6739 * Detects whether `T` is a comparable type. Basic types and structs and
6740 * classes that implement opCmp are ordering comparable.
6742 enum bool isOrderingComparable(T
) = is(typeof((ref T a
) => a
< a ?
1 : 0));
6747 static assert(isOrderingComparable
!int);
6748 static assert(isOrderingComparable
!string
);
6750 static struct Foo
{}
6751 static assert(!isOrderingComparable
!Foo
);
6756 auto opCmp(Bar b1
) const { return a
- b1
.a
; }
6761 assert(isOrderingComparable
!Bar
&& b2
> b1
);
6765 enum bool isEqualityComparable(T
) = is(typeof((ref T a
) => a
== a ?
1 : 0));
6769 static assert(isEqualityComparable
!int);
6770 static assert(isEqualityComparable
!string
);
6771 static assert(!isEqualityComparable
!void);
6774 static assert(isEqualityComparable
!Foo
);
6779 auto opEquals(Bar b1
) const { return a
== b1
.a
; }
6785 static assert(isEqualityComparable
!Bar
);
6791 $(RED Warning: This trait will be deprecated as soon as it is no longer used
6792 in Phobos. For a function parameter to safely accept a type
6793 that implicitly converts to string as a string, the conversion
6794 needs to happen at the callsite; otherwise, the conversion is
6795 done inside the function, and in many cases, that means that
6796 local memory is sliced (e.g. if a static array is passed to
6797 the function, then it's copied, and the resulting dynamic
6798 array will be a slice of a local variable). So, if the
6799 resulting string escapes the function, the string refers to
6800 invalid memory, and accessing it would mean accessing invalid
6801 memory. As such, the only safe way for a function to accept
6802 types that implicitly convert to string is for the implicit
6803 conversion to be done at the callsite, and that can only occur
6804 if the parameter is explicitly typed as an array, whereas
6805 using isConvertibleToString in a template constraint would
6806 result in the conversion being done inside the function. As
6807 such, isConvertibleToString is inherently unsafe and is going
6810 Detect whether `T` is a struct, static array, or enum that is implicitly
6811 convertible to a string.
6813 template isConvertibleToString(T
)
6815 enum isConvertibleToString
=
6816 (isAggregateType
!T || isStaticArray
!T ||
is(T
== enum))
6817 && is(StringTypeOf
!T
);
6823 static struct AliasedString
6829 enum StringEnum
{ a
= "foo" }
6831 assert(!isConvertibleToString
!string
);
6832 assert(isConvertibleToString
!AliasedString
);
6833 assert(isConvertibleToString
!StringEnum
);
6834 assert(isConvertibleToString
!(char[25]));
6835 assert(!isConvertibleToString
!(char[]));
6838 // https://issues.dlang.org/show_bug.cgi?id=16573
6841 enum I
: int { foo
= 1 }
6842 enum S
: string
{ foo
= "foo" }
6843 assert(!isConvertibleToString
!I
);
6844 assert(isConvertibleToString
!S
);
6847 package template convertToString(T
)
6849 static if (isConvertibleToString
!T
)
6850 alias convertToString
= StringTypeOf
!T
;
6852 alias convertToString
= T
;
6856 * Detect whether type `T` is a string that will be autodecoded.
6858 * Given a type `S` that is one of:
6860 * $(LI `const(char)[]`)
6861 * $(LI `const(wchar)[]`)
6863 * Type `T` can be one of:
6866 * $(LI implicitly convertible to `T`)
6867 * $(LI an enum with a base type `T`)
6868 * $(LI an aggregate with a base type `T`)
6870 * with the proviso that `T` cannot be a static array.
6873 * T = type to be tested
6876 * true if T represents a string that is subject to autodecoding
6879 * $(LREF isNarrowString)
6881 template isAutodecodableString(T
)
6883 import std
.range
.primitives
: autodecodeStrings
;
6885 enum isAutodecodableString
= autodecodeStrings
&&
6886 (is(T
: const char[]) ||
is(T
: const wchar[]))
6887 && !is(T
: U
[n
], U
, size_t n
)
6888 && !is(immutable T
: immutable noreturn
[]);
6894 static struct Stringish
6899 static assert(isAutodecodableString
!wstring
);
6900 static assert(isAutodecodableString
!Stringish
);
6901 static assert(!isAutodecodableString
!dstring
);
6903 enum E
: const(char)[3] { X
= "abc" }
6904 enum F
: const(char)[] { X
= "abc" }
6905 enum G
: F
{ X
= F
.init
}
6907 static assert(isAutodecodableString
!(char[]));
6908 static assert(!isAutodecodableString
!(E
));
6909 static assert(isAutodecodableString
!(F
));
6910 static assert(isAutodecodableString
!(G
));
6918 enum H
: Stringish
{ X
= Stringish() }
6919 enum I
: Stringish2
{ X
= Stringish2() }
6921 static assert(isAutodecodableString
!(H
));
6922 static assert(isAutodecodableString
!(I
));
6924 static assert(!isAutodecodableString
!(noreturn
[]));
6925 static assert(!isAutodecodableString
!(immutable(noreturn
)[]));
6929 * Detect whether type `T` is a static array.
6931 enum bool isStaticArray(T
) = __traits(isStaticArray
, T
);
6936 static assert( isStaticArray
!(int[3]));
6937 static assert( isStaticArray
!(const(int)[5]));
6938 static assert( isStaticArray
!(const(int)[][5]));
6940 static assert(!isStaticArray
!(const(int)[]));
6941 static assert(!isStaticArray
!(immutable(int)[]));
6942 static assert(!isStaticArray
!(const(int)[4][]));
6943 static assert(!isStaticArray
!(int[]));
6944 static assert(!isStaticArray
!(int[char]));
6945 static assert(!isStaticArray
!(int[1][]));
6946 static assert(!isStaticArray
!(int[int]));
6947 static assert(!isStaticArray
!int);
6952 static foreach (T
; AliasSeq
!(int[51], int[][2],
6953 char[][int][11], immutable char[13u],
6954 const(real)[1], const(real)[1][1], void[0]))
6956 static foreach (Q
; TypeQualifierList
)
6958 static assert( isStaticArray
!( Q
!T
));
6959 static assert(!isStaticArray
!( SubTypeOf
!(Q
!T
) ));
6963 //enum ESA : int[1] { a = [1], b = [2] }
6964 //static assert( isStaticArray!ESA);
6968 * Detect whether type `T` is a dynamic array.
6970 template isDynamicArray(T
)
6972 static if (is(T
== U
[], U
))
6973 enum bool isDynamicArray
= true;
6974 else static if (is(T U
== enum))
6975 // BUG: isDynamicArray / isStaticArray considers enums
6976 // with appropriate base types as dynamic/static arrays
6977 // Retain old behaviour for now, see
6978 // https://github.com/dlang/phobos/pull/7574
6979 enum bool isDynamicArray
= isDynamicArray
!U
;
6981 enum bool isDynamicArray
= false;
6987 static assert( isDynamicArray
!(int[]));
6988 static assert( isDynamicArray
!(string
));
6989 static assert( isDynamicArray
!(long[3][]));
6991 static assert(!isDynamicArray
!(int[5]));
6992 static assert(!isDynamicArray
!(typeof(null)));
6997 import std
.meta
: AliasSeq
;
6998 static foreach (T
; AliasSeq
!(int[], char[], string
, long[3][], double[string
][]))
7000 static foreach (Q
; TypeQualifierList
)
7002 static assert( isDynamicArray
!( Q
!T
));
7003 static assert(!isDynamicArray
!( SubTypeOf
!(Q
!T
) ));
7007 static assert(!isDynamicArray
!(int[5]));
7009 static struct AliasThis
7015 static assert(!isDynamicArray
!AliasThis
);
7017 // https://github.com/dlang/phobos/pull/7574/files#r464115492
7023 static assert( isDynamicArray
!E
);
7027 * Detect whether type `T` is an array (static or dynamic; for associative
7028 * arrays see $(LREF isAssociativeArray)).
7030 enum bool isArray(T
) = isStaticArray
!T || isDynamicArray
!T
;
7035 static assert( isArray
!(int[]));
7036 static assert( isArray
!(int[5]));
7037 static assert( isArray
!(string
));
7039 static assert(!isArray
!uint);
7040 static assert(!isArray
!(uint[uint]));
7041 static assert(!isArray
!(typeof(null)));
7046 import std
.meta
: AliasSeq
;
7047 static foreach (T
; AliasSeq
!(int[], int[5], void[]))
7049 static foreach (Q
; TypeQualifierList
)
7051 static assert( isArray
!(Q
!T
));
7052 static assert(!isArray
!(SubTypeOf
!(Q
!T
)));
7058 * Detect whether `T` is an associative array type
7060 enum bool isAssociativeArray(T
) = __traits(isAssociativeArray
, T
);
7067 static assert( isAssociativeArray
!(int[string
]));
7068 static assert( isAssociativeArray
!(S
[S
]));
7069 static assert(!isAssociativeArray
!(string
[]));
7070 static assert(!isAssociativeArray
!S
);
7071 static assert(!isAssociativeArray
!(int[4]));
7078 @property uint[] keys() { return null; }
7079 @property uint[] values() { return null; }
7082 static foreach (T
; AliasSeq
!(int[int], int[string
], immutable(char[5])[int]))
7084 static foreach (Q
; TypeQualifierList
)
7086 static assert( isAssociativeArray
!(Q
!T
));
7087 static assert(!isAssociativeArray
!(SubTypeOf
!(Q
!T
)));
7091 static assert(!isAssociativeArray
!Foo
);
7092 static assert(!isAssociativeArray
!int);
7093 static assert(!isAssociativeArray
!(int[]));
7094 static assert(!isAssociativeArray
!(typeof(null)));
7096 //enum EAA : int[int] { a = [1:1], b = [2:2] }
7097 //static assert( isAssociativeArray!EAA);
7101 * Detect whether type `T` is a builtin type.
7103 enum bool isBuiltinType(T
) = is(BuiltinTypeOf
!T
) && !isAggregateType
!T
;
7113 static assert( isBuiltinType
!void);
7114 static assert( isBuiltinType
!string
);
7115 static assert( isBuiltinType
!(int[]));
7116 static assert( isBuiltinType
!(C
[string
]));
7117 static assert( isBuiltinType
!(typeof(null)));
7118 static assert(!isBuiltinType
!C
);
7119 static assert(!isBuiltinType
!U
);
7120 static assert(!isBuiltinType
!S
);
7121 static assert(!isBuiltinType
!I
);
7122 static assert(!isBuiltinType
!(void delegate(int)));
7126 * Detect whether type `T` is a SIMD vector type.
7128 enum bool isSIMDVector(T
) = is(T
: __vector(V
[N
]), V
, size_t N
);
7133 static if (is(__vector(float[4])))
7135 alias SimdVec
= __vector(float[4]);
7136 static assert(isSIMDVector
!(__vector(float[4])));
7137 static assert(isSIMDVector
!SimdVec
);
7139 static assert(!isSIMDVector
!uint);
7140 static assert(!isSIMDVector
!(float[4]));
7144 * Detect whether type `T` is a pointer.
7146 enum bool isPointer(T
) = is(T
== U
*, U
);
7153 static assert( isPointer
!(int*));
7154 static assert( isPointer
!(int function()));
7155 static assert(!isPointer
!int);
7156 static assert(!isPointer
!string
);
7157 static assert(!isPointer
!(typeof(null)));
7158 static assert(!isPointer
!(typeof(fun
)));
7159 static assert(!isPointer
!(int delegate()));
7164 static foreach (T
; AliasSeq
!(int*, void*, char[]*))
7166 static foreach (Q
; TypeQualifierList
)
7168 static assert( isPointer
!(Q
!T
));
7169 static assert(!isPointer
!(SubTypeOf
!(Q
!T
)));
7173 static assert(!isPointer
!uint);
7174 static assert(!isPointer
!(uint[uint]));
7175 static assert(!isPointer
!(char[]));
7176 static assert(!isPointer
!(typeof(null)));
7180 Returns the target type of a pointer.
7182 alias PointerTarget(T
: T
*) = T
;
7187 static assert(is(PointerTarget
!(int*) == int));
7188 static assert(is(PointerTarget
!(void*) == void));
7192 * Detect whether type `T` is an aggregate type.
7194 enum bool isAggregateType(T
) = is(T
== struct) ||
is(T
== union) ||
7195 is(T
== class) ||
is(T
== interface);
7205 static assert( isAggregateType
!C
);
7206 static assert( isAggregateType
!U
);
7207 static assert( isAggregateType
!S
);
7208 static assert( isAggregateType
!I
);
7209 static assert(!isAggregateType
!void);
7210 static assert(!isAggregateType
!string
);
7211 static assert(!isAggregateType
!(int[]));
7212 static assert(!isAggregateType
!(C
[string
]));
7213 static assert(!isAggregateType
!(void delegate(int)));
7217 * Returns `true` if T can be iterated over using a `foreach` loop with
7218 * a single loop variable of automatically inferred type, regardless of how
7219 * the `foreach` loop is implemented. This includes ranges, structs/classes
7220 * that define `opApply` with a single loop variable, and builtin dynamic,
7221 * static and associative arrays.
7223 enum bool isIterable(T
) = is(typeof({ foreach (elem
; T
.init
) {} }));
7230 int opApply(scope int delegate(ref uint) dg
) { assert(0); }
7235 @property uint front() { assert(0); }
7236 void popFront() { assert(0); }
7237 enum bool empty
= false;
7240 static assert( isIterable
!(uint[]));
7241 static assert( isIterable
!OpApply
);
7242 static assert( isIterable
!(uint[string
]));
7243 static assert( isIterable
!Range
);
7245 static assert(!isIterable
!uint);
7249 * Returns true if T is not const or immutable. Note that isMutable is true for
7250 * string, or immutable(char)[], because the 'head' is mutable.
7252 enum bool isMutable(T
) = !is(T
== const) && !is(T
== immutable) && !is(T
== inout);
7257 static assert( isMutable
!int);
7258 static assert( isMutable
!string
);
7259 static assert( isMutable
!(shared int));
7260 static assert( isMutable
!(shared const(int)[]));
7262 static assert(!isMutable
!(const int));
7263 static assert(!isMutable
!(inout int));
7264 static assert(!isMutable
!(shared(const int)));
7265 static assert(!isMutable
!(shared(inout int)));
7266 static assert(!isMutable
!(immutable string
));
7270 * Returns true if T is an instance of the template S.
7272 enum bool isInstanceOf(alias S
, T
) = is(T
== S
!Args
, Args
...);
7274 template isInstanceOf(alias S
, alias T
)
7276 enum impl(alias T
: S
!Args
, Args
...) = true;
7277 enum impl(alias T
) = false;
7278 enum isInstanceOf
= impl
!T
;
7284 static struct Foo(T
...) { }
7285 static struct Bar(T
...) { }
7286 static struct Doo(T
) { }
7287 static struct ABC(int x
) { }
7288 static void fun(T
)() { }
7289 template templ(T
) { }
7291 static assert(isInstanceOf
!(Foo
, Foo
!int));
7292 static assert(!isInstanceOf
!(Foo
, Bar
!int));
7293 static assert(!isInstanceOf
!(Foo
, int));
7294 static assert(isInstanceOf
!(Doo
, Doo
!int));
7295 static assert(isInstanceOf
!(ABC
, ABC
!1));
7296 static assert(!isInstanceOf
!(Foo
, Foo
));
7297 static assert(isInstanceOf
!(fun
, fun
!int));
7298 static assert(isInstanceOf
!(templ
, templ
!int));
7302 * To use `isInstanceOf` to check the identity of a template while inside of said
7303 * template, use $(LREF TemplateOf).
7307 static struct A(T
= void)
7309 // doesn't work as expected, only accepts A when T = void
7310 void func(B
)(B b
) if (isInstanceOf
!(A
, B
)) {}
7313 void method(B
)(B b
) if (isInstanceOf
!(TemplateOf
!(A
), B
)) {}
7320 static assert(!__traits(compiles
, a1
.func(a3
)));
7321 static assert( __traits(compiles
, a1
.method(a2
)));
7322 static assert( __traits(compiles
, a1
.method(a3
)));
7327 static void fun1(T
)() { }
7328 static void fun2(T
)() { }
7329 template templ1(T
) { }
7330 template templ2(T
) { }
7332 static assert(!isInstanceOf
!(fun1
, fun2
!int));
7333 static assert(!isInstanceOf
!(templ1
, templ2
!int));
7337 * Check whether the tuple T is an expression tuple.
7338 * An expression tuple only contains expressions.
7340 * See_Also: $(LREF isTypeTuple).
7342 template isExpressions(T
...)
7344 static foreach (Ti
; T
)
7346 static if (!is(typeof(isExpressions
) == bool) && // not yet defined
7347 (is(Ti
) ||
!__traits(compiles
, { auto ex
= Ti
; })))
7349 enum isExpressions
= false;
7352 static if (!is(typeof(isExpressions
) == bool)) // if not yet defined
7354 enum isExpressions
= true;
7361 static assert(isExpressions
!(1, 2.0, "a"));
7362 static assert(!isExpressions
!(int, double, string
));
7363 static assert(!isExpressions
!(int, 2.0, "a"));
7367 * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7370 alias isExpressionTuple
= isExpressions
;
7375 static int bar() { return 42; }
7376 immutable aa
= [ 1: -1 ];
7379 static assert( isExpressionTuple
!(42));
7380 static assert( isExpressionTuple
!aa
);
7381 static assert( isExpressionTuple
!("cattywampus", 2.7, aa
));
7382 static assert( isExpressionTuple
!(bar()));
7384 static assert(!isExpressionTuple
!isExpressionTuple
);
7385 static assert(!isExpressionTuple
!foo
);
7386 static assert(!isExpressionTuple
!( (a
) { } ));
7387 static assert(!isExpressionTuple
!int);
7388 static assert(!isExpressionTuple
!myint
);
7393 * Check whether the tuple `T` is a type tuple.
7394 * A type tuple only contains types.
7396 * See_Also: $(LREF isExpressions).
7398 enum isTypeTuple(T
...) =
7400 static foreach (U
; T
)
7410 static assert(isTypeTuple
!(int, float, string
));
7411 static assert(!isTypeTuple
!(1, 2.0, "a"));
7412 static assert(!isTypeTuple
!(1, double, string
));
7422 static assert( isTypeTuple
!int);
7423 static assert( isTypeTuple
!string
);
7424 static assert( isTypeTuple
!C
);
7425 static assert( isTypeTuple
!(typeof(func
)));
7426 static assert( isTypeTuple
!(int, char, double));
7428 static assert(!isTypeTuple
!c
);
7429 static assert(!isTypeTuple
!isTypeTuple
);
7430 static assert(!isTypeTuple
!CONST
);
7435 Detect whether symbol or type `T` is a function pointer.
7437 enum bool isFunctionPointer(alias T
) = is(typeof(*T
) == function);
7442 static void foo() {}
7446 static assert( isFunctionPointer
!fpfoo
);
7447 static assert( isFunctionPointer
!(void function()));
7450 static assert(!isFunctionPointer
!dgbar
);
7451 static assert(!isFunctionPointer
!(void delegate()));
7452 static assert(!isFunctionPointer
!foo
);
7453 static assert(!isFunctionPointer
!bar
);
7455 static assert( isFunctionPointer
!((int a
) {}));
7459 Detect whether symbol or type `T` is a delegate.
7461 enum bool isDelegate(alias T
) = is(typeof(T
) == delegate) ||
is(T
== delegate);
7466 static void sfunc() { }
7468 void func() { x
++; }
7471 assert(isDelegate
!dg
);
7472 assert(isDelegate
!(int delegate()));
7473 assert(isDelegate
!(typeof(&func
)));
7476 assert(!isDelegate
!fp
);
7477 assert(!isDelegate
!(int function()));
7478 assert(!isDelegate
!(typeof(&sfunc
)));
7482 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7485 T = The type to check
7489 enum bool isSomeFunction(alias T
) =
7491 is(typeof(T
) == return) ||
7492 is(typeof(&T
) == return); // @property
7497 static real func(ref int) { return 0; }
7498 static void prop() @property { }
7501 real method(ref int) { return 0; }
7502 real prop() @property { return 0; }
7506 auto dg
= &c
.method
;
7508 static assert( isSomeFunction
!func
);
7509 static assert( isSomeFunction
!prop
);
7510 static assert( isSomeFunction
!(C
.method
));
7511 static assert( isSomeFunction
!(C
.prop
));
7512 static assert( isSomeFunction
!(c
.prop
));
7513 static assert( isSomeFunction
!fp
);
7514 static assert( isSomeFunction
!dg
);
7517 static assert(!isSomeFunction
!int);
7518 static assert(!isSomeFunction
!val
);
7523 void nestedFunc() { }
7524 void nestedProp() @property { }
7525 static assert(isSomeFunction
!nestedFunc
);
7526 static assert(isSomeFunction
!nestedProp
);
7527 static assert(isSomeFunction
!(real function(ref int)));
7528 static assert(isSomeFunction
!(real delegate(ref int)));
7529 static assert(isSomeFunction
!((int a
) { return a
; }));
7530 static assert(!isSomeFunction
!isSomeFunction
);
7534 Detect whether `T` is a callable object, which can be called with the
7535 function call operator `$(LPAREN)...$(RPAREN)`.
7537 template isCallable(alias callable
)
7539 static if (is(typeof(&callable
.opCall
) == delegate))
7540 // T is a object which has a member function opCall().
7541 enum bool isCallable
= true;
7542 else static if (is(typeof(&callable
.opCall
) V
: V
*) && is(V
== function))
7543 // T is a type which has a static member function opCall().
7544 enum bool isCallable
= true;
7545 else static if (is(typeof(&callable
.opCall
!())))
7547 alias TemplateInstanceType
= typeof(&callable
.opCall
!());
7548 enum bool isCallable
= isCallable
!TemplateInstanceType
;
7550 else static if (is(typeof(&callable
!())))
7552 alias TemplateInstanceType
= typeof(&callable
!());
7553 enum bool isCallable
= isCallable
!TemplateInstanceType
;
7557 enum bool isCallable
= isSomeFunction
!callable
;
7561 /// Functions, lambdas, and aggregate types with (static) opCall.
7565 int g(int x
) { return x
; }
7567 static assert( isCallable
!f
);
7568 static assert( isCallable
!g
);
7570 class C
{ int opCall(int) { return 0; } }
7572 struct S
{ static int opCall(int) { return 0; } }
7573 interface I
{ real value() @property; }
7575 static assert( isCallable
!c
);
7576 static assert( isCallable
!(c
.opCall
));
7577 static assert( isCallable
!S
);
7578 static assert( isCallable
!(I
.value
));
7579 static assert( isCallable
!((int a
) { return a
; }));
7581 static assert(!isCallable
!I
);
7588 T
g(T
= int)(T x
) { return x
; }
7589 struct S1
{ static void opCall()() { } }
7590 struct S2
{ static T
opCall(T
= int)(T x
) {return x
; } }
7592 static assert( isCallable
!f
);
7593 static assert( isCallable
!g
);
7594 static assert( isCallable
!S1
);
7595 static assert( isCallable
!S2
);
7598 /// Overloaded functions and function templates.
7601 static struct Wrapper
7604 int f(int x
) { return x
; }
7607 T
g(T
= int)(T x
) { return x
; }
7610 static assert(isCallable
!(Wrapper
.f
));
7611 static assert(isCallable
!(Wrapper
.g
));
7616 Detect whether `T` is an abstract function.
7619 T = The type to check
7623 enum isAbstractFunction(alias T
) = __traits(isAbstractFunction
, T
);
7628 struct S
{ void foo() { } }
7629 class C
{ void foo() { } }
7630 class AC
{ abstract void foo(); }
7631 static assert(!isAbstractFunction
!(int));
7632 static assert(!isAbstractFunction
!(S
.foo
));
7633 static assert(!isAbstractFunction
!(C
.foo
));
7634 static assert( isAbstractFunction
!(AC
.foo
));
7638 * Detect whether `T` is a final function.
7640 enum isFinalFunction(alias T
) = __traits(isFinalFunction
, T
);
7645 struct S
{ void bar() { } }
7646 final class FC
{ void foo(); }
7652 static assert(!isFinalFunction
!(int));
7653 static assert(!isFinalFunction
!(S
.bar
));
7654 static assert( isFinalFunction
!(FC
.foo
));
7655 static assert(!isFinalFunction
!(C
.bar
));
7656 static assert( isFinalFunction
!(C
.foo
));
7660 Determines if `f` is a function that requires a context pointer.
7663 f = The type to check
7667 template isNestedFunction(alias f
)
7669 enum isNestedFunction
= __traits(isNested
, f
) && isSomeFunction
!(f
);
7679 int f() { return i
; }
7681 static assert(isNestedFunction
!(f
));
7684 static assert(!isNestedFunction
!f
);
7687 // https://issues.dlang.org/show_bug.cgi?id=18669
7699 int bar() { return i
; }
7701 static assert(!isNestedFunction
!(Outer
.Inner
));
7702 static assert(!isNestedFunction
!(SS
));
7706 * Detect whether `T` is an abstract class.
7708 enum isAbstractClass(alias T
) = __traits(isAbstractClass
, T
);
7715 abstract class AC
{ }
7716 static assert(!isAbstractClass
!S
);
7717 static assert(!isAbstractClass
!C
);
7718 static assert( isAbstractClass
!AC
);
7720 static assert(!isAbstractClass
!c
);
7722 static assert( isAbstractClass
!ac
);
7726 * Detect whether `T` is a final class.
7728 enum isFinalClass(alias T
) = __traits(isFinalClass
, T
);
7734 abstract class AC
{ }
7735 final class FC1
: C
{ }
7737 static assert(!isFinalClass
!C
);
7738 static assert(!isFinalClass
!AC
);
7739 static assert( isFinalClass
!FC1
);
7740 static assert( isFinalClass
!FC2
);
7742 static assert(!isFinalClass
!c
);
7744 static assert( isFinalClass
!fc1
);
7747 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7749 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7754 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7758 import core
.internal
.traits
: CoreUnconst
= Unconst
;
7759 alias Unconst
= CoreUnconst
!(T
);
7764 import core
.internal
.traits
: CoreUnconst
= Unconst
;
7765 alias Unconst
= CoreUnconst
;
7771 static assert(is(Unconst
!int == int));
7772 static assert(is(Unconst
!(const int) == int));
7773 static assert(is(Unconst
!(immutable int) == int));
7774 static assert(is(Unconst
!(shared int) == shared int));
7775 static assert(is(Unconst
!(shared(const int)) == shared int));
7780 static assert(is(Unconst
!( int) == int));
7781 static assert(is(Unconst
!( const int) == int));
7782 static assert(is(Unconst
!( inout int) == int));
7783 static assert(is(Unconst
!( inout const int) == int));
7784 static assert(is(Unconst
!(shared int) == shared int));
7785 static assert(is(Unconst
!(shared const int) == shared int));
7786 static assert(is(Unconst
!(shared inout int) == shared int));
7787 static assert(is(Unconst
!(shared inout const int) == shared int));
7788 static assert(is(Unconst
!( immutable int) == int));
7790 alias ImmIntArr
= immutable(int[]);
7791 static assert(is(Unconst
!ImmIntArr
== immutable(int)[]));
7797 Removes all qualifiers, if any, from type `T`.
7801 import core
.internal
.traits
: CoreUnqual
= Unqual
;
7802 alias Unqual
= CoreUnqual
!(T
);
7807 import core
.internal
.traits
: CoreUnqual
= Unqual
;
7808 alias Unqual
= CoreUnqual
;
7814 static assert(is(Unqual
!int == int));
7815 static assert(is(Unqual
!(const int) == int));
7816 static assert(is(Unqual
!(immutable int) == int));
7817 static assert(is(Unqual
!(shared int) == int));
7818 static assert(is(Unqual
!(shared(const int)) == int));
7823 static assert(is(Unqual
!( int) == int));
7824 static assert(is(Unqual
!( const int) == int));
7825 static assert(is(Unqual
!( inout int) == int));
7826 static assert(is(Unqual
!( inout const int) == int));
7827 static assert(is(Unqual
!(shared int) == int));
7828 static assert(is(Unqual
!(shared const int) == int));
7829 static assert(is(Unqual
!(shared inout int) == int));
7830 static assert(is(Unqual
!(shared inout const int) == int));
7831 static assert(is(Unqual
!( immutable int) == int));
7833 alias ImmIntArr
= immutable(int[]);
7834 static assert(is(Unqual
!ImmIntArr
== immutable(int)[]));
7837 // [For internal use]
7838 package template ModifyTypePreservingTQ(alias Modifier
, T
)
7840 import core
.internal
.traits
: _ModifyTypePreservingTQ
= ModifyTypePreservingTQ
;
7841 alias ModifyTypePreservingTQ
= _ModifyTypePreservingTQ
!(Modifier
, T
);
7845 * Copies type qualifiers from `FromType` to `ToType`.
7847 * Supported type qualifiers:
7855 template CopyTypeQualifiers(FromType
, ToType
)
7857 alias T(U
) = ToType
;
7858 alias CopyTypeQualifiers
= ModifyTypePreservingTQ
!(T
, FromType
);
7864 static assert(is(CopyTypeQualifiers
!(inout const real, int) == inout const int));
7869 static assert(is(CopyTypeQualifiers
!( real, int) == int));
7870 static assert(is(CopyTypeQualifiers
!( const real, int) == const int));
7871 static assert(is(CopyTypeQualifiers
!( inout real, int) == inout int));
7872 static assert(is(CopyTypeQualifiers
!( inout const real, int) == inout const int));
7873 static assert(is(CopyTypeQualifiers
!(shared real, int) == shared int));
7874 static assert(is(CopyTypeQualifiers
!(shared const real, int) == shared const int));
7875 static assert(is(CopyTypeQualifiers
!(shared inout real, int) == shared inout int));
7876 static assert(is(CopyTypeQualifiers
!(shared inout const real, int) == shared inout const int));
7877 static assert(is(CopyTypeQualifiers
!( immutable real, int) == immutable int));
7881 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
7882 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
7883 returned type will be the same as `ToType`.
7885 template CopyConstness(FromType
, ToType
)
7887 alias Unshared(T
) = T
;
7888 alias Unshared(T
: shared U
, U
) = U
;
7890 alias CopyConstness
= Unshared
!(CopyTypeQualifiers
!(FromType
, ToType
));
7897 CopyConstness
!(typeof(i
), float) f
;
7898 assert( is(typeof(f
) == const float));
7900 CopyConstness
!(char, uint) u
;
7901 assert( is(typeof(u
) == uint));
7903 //The 'shared' qualifier will not be copied
7904 assert(!is(CopyConstness
!(shared bool, int) == shared int));
7906 //But the constness will be
7907 assert( is(CopyConstness
!(shared const real, double) == const double));
7909 //Careful, const(int)[] is a mutable array of const(int)
7910 alias MutT
= CopyConstness
!(const(int)[], int);
7911 assert(!is(MutT
== const(int)));
7913 //Okay, const(int[]) applies to array and contained ints
7914 alias CstT
= CopyConstness
!(const(int[]), int);
7915 assert( is(CstT
== const(int)));
7923 void method2() const {}
7924 void method3() immutable {}
7927 assert(is(CopyConstness
!(typeof(Test
.method1
), real) == real));
7929 assert(is(CopyConstness
!(typeof(Test
.method2
), byte) == const(byte)));
7931 assert(is(CopyConstness
!(typeof(Test
.method3
), string
) == immutable(string
)));
7936 assert(is(CopyConstness
!(inout(int)[], int[]) == int[]));
7937 assert(is(CopyConstness
!(inout(int[]), int[]) == inout(int[])));
7942 static assert(is(CopyConstness
!( int, real) == real));
7943 static assert(is(CopyConstness
!(const int, real) == const real));
7944 static assert(is(CopyConstness
!(inout int, real) == inout real));
7945 static assert(is(CopyConstness
!(inout const int, real) == inout const real));
7946 static assert(is(CopyConstness
!(shared int, real) == real));
7947 static assert(is(CopyConstness
!(shared const int, real) == const real));
7948 static assert(is(CopyConstness
!(shared inout int, real) == inout real));
7949 static assert(is(CopyConstness
!(shared inout const int, real) == inout const real));
7950 static assert(is(CopyConstness
!(immutable int, real) == immutable real));
7954 Returns the inferred type of the loop variable when a variable of type T
7955 is iterated over using a `foreach` loop with a single loop variable and
7956 automatically inferred return type. Note that this may not be the same as
7957 `std.range.ElementType!Range` in the case of narrow strings, or if T
7958 has both opApply and a range interface.
7960 template ForeachType(T
)
7962 alias ForeachType
= typeof(
7965 foreach (elem
; T
.init
)
7976 static assert(is(ForeachType
!(uint[]) == uint));
7977 static assert(is(ForeachType
!string
== immutable(char)));
7978 static assert(is(ForeachType
!(string
[string
]) == string
));
7979 static assert(is(ForeachType
!(inout(int)[]) == inout(int)));
7984 * Strips off all `enum`s from type `T`.
7986 template OriginalType(T
)
7988 import core
.internal
.traits
: _OriginalType
= OriginalType
;
7989 alias OriginalType
= _OriginalType
!T
;
7995 enum E
: real { a
= 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
7996 enum F
: E
{ a
= E
.a
}
7998 static assert(is(OriginalType
!E
== real));
7999 static assert(is(OriginalType
!F
== real));
8000 static assert(is(OriginalType
!G
== const real));
8004 * Get the Key type of an Associative Array.
8006 alias KeyType(V
: V
[K
], K
) = K
;
8011 alias Hash
= int[string
];
8012 static assert(is(KeyType
!Hash
== string
));
8013 static assert(is(ValueType
!Hash
== int));
8014 KeyType
!Hash
str = "a"; // str is declared as string
8015 ValueType
!Hash num
= 1; // num is declared as int
8019 * Get the Value type of an Associative Array.
8021 alias ValueType(V
: V
[K
], K
) = V
;
8026 alias Hash
= int[string
];
8027 static assert(is(KeyType
!Hash
== string
));
8028 static assert(is(ValueType
!Hash
== int));
8029 KeyType
!Hash
str = "a"; // str is declared as string
8030 ValueType
!Hash num
= 1; // num is declared as int
8035 T = A built in integral or vector type.
8038 The corresponding unsigned numeric type for `T` with the
8039 same type qualifiers.
8041 If `T` is not a integral or vector, a compile-time error is given.
8043 template Unsigned(T
)
8047 static if (is(T
: __vector(V
[N
]), V
, size_t N
))
8048 alias Impl
= __vector(Impl
!V
[N
]);
8049 else static if (isUnsigned
!T
)
8051 else static if (isSigned
!T
&& !isFloatingPoint
!T
)
8053 static if (is(T
== byte )) alias Impl
= ubyte;
8054 static if (is(T
== short)) alias Impl
= ushort;
8055 static if (is(T
== int )) alias Impl
= uint;
8056 static if (is(T
== long )) alias Impl
= ulong;
8057 static if (is(ucent) && is(T
== cent )) alias Impl
= ucent;
8060 static assert(false, "Type " ~ T
.stringof
~
8061 " does not have an Unsigned counterpart");
8064 alias Unsigned
= ModifyTypePreservingTQ
!(Impl
, OriginalType
!T
);
8070 static assert(is(Unsigned
!(int) == uint));
8071 static assert(is(Unsigned
!(long) == ulong));
8072 static assert(is(Unsigned
!(const short) == const ushort));
8073 static assert(is(Unsigned
!(immutable byte) == immutable ubyte));
8074 static assert(is(Unsigned
!(inout int) == inout uint));
8078 /// Unsigned types are forwarded
8081 static assert(is(Unsigned
!(uint) == uint));
8082 static assert(is(Unsigned
!(const uint) == const uint));
8084 static assert(is(Unsigned
!(ubyte) == ubyte));
8085 static assert(is(Unsigned
!(immutable uint) == immutable uint));
8090 alias U1
= Unsigned
!int;
8091 alias U2
= Unsigned
!(const(int));
8092 alias U3
= Unsigned
!(immutable(int));
8093 static assert(is(U1
== uint));
8094 static assert(is(U2
== const(uint)));
8095 static assert(is(U3
== immutable(uint)));
8096 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8098 alias UV1
= Unsigned
!(__vector(int[4]));
8099 alias UV2
= Unsigned
!(const(__vector(int[4])));
8100 static assert(is(UV1
== __vector(uint[4])));
8101 static assert(is(UV2
== const(__vector(uint[4]))));
8104 //alias U2 = Unsigned!S;
8105 //alias U3 = Unsigned!double;
8106 static if (is(ucent))
8108 alias U4
= Unsigned
!cent;
8109 alias U5
= Unsigned
!(const(cent));
8110 alias U6
= Unsigned
!(immutable(cent));
8111 static assert(is(U4
== ucent));
8112 static assert(is(U5
== const(ucent)));
8113 static assert(is(U6
== immutable(ucent)));
8118 Returns the largest type, i.e. T such that T.sizeof is the largest. If more
8119 than one type is of the same size, the leftmost argument of these in will be
8122 template Largest(T
...)
8125 alias Largest
= T
[0];
8126 static foreach (U
; T
[1 .. $])
8127 Largest
= Select
!(U
.sizeof
> Largest
.sizeof
, U
, Largest
);
8133 static assert(is(Largest
!(uint, ubyte, ushort, real) == real));
8134 static assert(is(Largest
!(ulong, double) == ulong));
8135 static assert(is(Largest
!(double, ulong) == double));
8136 static assert(is(Largest
!(uint, byte, double, short) == double));
8137 static if (is(ucent))
8138 static assert(is(Largest
!(uint, ubyte, ucent, ushort) == ucent));
8142 Returns the corresponding signed type for T. T must be a numeric integral type,
8143 otherwise a compile-time error occurs.
8149 static if (is(T
: __vector(V
[N
]), V
, size_t N
))
8150 alias Impl
= __vector(Impl
!V
[N
]);
8151 else static if (isSigned
!T
)
8153 else static if (isUnsigned
!T
)
8155 static if (is(T
== ubyte )) alias Impl
= byte;
8156 static if (is(T
== ushort)) alias Impl
= short;
8157 static if (is(T
== uint )) alias Impl
= int;
8158 static if (is(T
== ulong )) alias Impl
= long;
8159 static if (is(ucent) && is(T
== ucent )) alias Impl
= cent;
8162 static assert(false, "Type " ~ T
.stringof
~
8163 " does not have an Signed counterpart");
8166 alias Signed
= ModifyTypePreservingTQ
!(Impl
, OriginalType
!T
);
8172 alias S1
= Signed
!uint;
8173 static assert(is(S1
== int));
8174 alias S2
= Signed
!(const(uint));
8175 static assert(is(S2
== const(int)));
8176 alias S3
= Signed
!(immutable(uint));
8177 static assert(is(S3
== immutable(int)));
8178 static if (is(ucent))
8180 alias S4
= Signed
!ucent;
8181 static assert(is(S4
== cent));
8187 static assert(is(Signed
!float == float));
8188 static if (is(__vector(int[4])) && is(__vector(uint[4])))
8190 alias SV1
= Signed
!(__vector(uint[4]));
8191 alias SV2
= Signed
!(const(__vector(uint[4])));
8192 static assert(is(SV1
== __vector(int[4])));
8193 static assert(is(SV2
== const(__vector(int[4]))));
8199 Returns the most negative value of the numeric type T.
8201 template mostNegative(T
)
8202 if (isNumeric
!T || isSomeChar
!T || isBoolean
!T
)
8204 static if (is(typeof(T
.min_normal
)))
8205 enum mostNegative
= -T
.max
;
8206 else static if (T
.min
== 0)
8207 enum byte mostNegative
= 0;
8209 enum mostNegative
= T
.min
;
8215 static assert(mostNegative
!float == -float.max
);
8216 static assert(mostNegative
!double == -double.max
);
8217 static assert(mostNegative
!real == -real.max
);
8218 static assert(mostNegative
!bool == false);
8224 import std
.meta
: AliasSeq
;
8226 static foreach (T
; AliasSeq
!(bool, byte, short, int, long))
8227 static assert(mostNegative
!T
== T
.min
);
8229 static foreach (T
; AliasSeq
!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8230 static assert(mostNegative
!T
== 0);
8234 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8235 to in multi-term arithmetic expressions.
8237 template Promoted(T
)
8240 alias Promoted
= CopyTypeQualifiers
!(T
, typeof(T
.init
+ T
.init
));
8247 static assert(is(typeof(a
* b
) == Promoted
!ubyte));
8248 static assert(is(Promoted
!ubyte == int));
8250 static assert(is(Promoted
!(shared(bool)) == shared(int)));
8251 static assert(is(Promoted
!(const(int)) == const(int)));
8252 static assert(is(Promoted
!double == double));
8258 static foreach (T
; AliasSeq
!(bool, byte, ubyte, short, ushort, char, wchar))
8260 static assert(is(Promoted
!T
== int));
8261 static assert(is(Promoted
!(shared(const T
)) == shared(const int)));
8264 // already promoted:
8265 static foreach (T
; AliasSeq
!(int, uint, long, ulong, float, double, real))
8267 static assert(is(Promoted
!T
== T
));
8268 static assert(is(Promoted
!(immutable(T
)) == immutable(T
)));
8272 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8274 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8277 Returns the mangled name of symbol or type `sth`.
8279 `mangledName` is the same as builtin `.mangleof` property, but
8280 might be more convenient in generic code, e.g. as a template argument
8281 when invoking staticMap.
8283 enum mangledName(alias sth
) = sth
.mangleof
;
8288 import std
.meta
: AliasSeq
;
8289 alias TL
= staticMap
!(mangledName
, int, const int, immutable int);
8290 static assert(TL
== AliasSeq
!("i", "xi", "yi"));
8293 version (StdUnittest
) private void freeFunc(string
);
8297 class C
{ int value() @property { return 0; } }
8298 static assert(mangledName
!int == int.mangleof
);
8299 static assert(mangledName
!C
== C
.mangleof
);
8300 static assert(mangledName
!(C
.value
) == C
.value
.mangleof
);
8301 static assert(mangledName
!(C
.value
)[$ - 12 .. $] == "5valueMFNdZi");
8302 static assert(mangledName
!mangledName
== "3std6traits11mangledName");
8303 static assert(mangledName
!freeFunc
== "_D3std6traits8freeFuncFAyaZv");
8305 // https://issues.dlang.org/show_bug.cgi?id=9148
8306 static if (is(typeof({ return x
; }) : int delegate() pure))
8307 static assert(mangledName
!((int a
) { return a
+x
; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc
8309 static assert(mangledName
!((int a
) { return a
+x
; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc
8314 // @system due to demangle
8315 // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8316 import std
.demangle
: demangle
;
8318 auto foo_demangled
= demangle(mangledName
!foo
);
8319 assert(foo_demangled
[0 .. 4] == "int " && foo_demangled
[$-3 .. $] == "foo",
8323 auto bar_demangled
= demangle(mangledName
!bar
);
8324 assert(bar_demangled
[0 .. 5] == "void " && bar_demangled
[$-5 .. $] == "bar()");
8329 // XXX Select & select should go to another module. (functional or algorithm?)
8332 Aliases itself to `T[0]` if the boolean `condition` is `true`
8333 and to `T[1]` otherwise.
8335 template Select(bool condition
, T
...)
8338 import std
.meta
: Alias
;
8339 alias Select
= Alias
!(T
[!condition
]);
8346 static assert(is(Select
!(true, int, long) == int));
8347 static assert(is(Select
!(false, int, long) == long));
8348 static struct Foo
{}
8349 static assert(is(Select
!(false, const(int), const(Foo
)) == const(Foo
)));
8351 // can select symbols
8354 alias selA
= Select
!(true, a
, b
);
8355 alias selB
= Select
!(false, a
, b
);
8359 // can select (compile-time) expressions
8360 enum val
= Select
!(false, -4, 9 - 6);
8361 static assert(val
== 3);
8365 Select one of two functions to run via template parameter.
8368 cond = A `bool` which determines which function is run
8369 a = The first function
8370 b = The second function
8373 `a` without evaluating `b` if `cond` is `true`.
8374 Otherwise, returns `b` without evaluating `a`.
8376 A
select(bool cond
: true, A
, B
)(A a
, lazy B b
) { return a
; }
8378 B
select(bool cond
: false, A
, B
)(lazy A a
, B b
) { return b
; }
8383 real run() { return 0; }
8384 int fail() { assert(0); }
8385 auto a
= select
!true(run(), fail());
8386 auto b
= select
!false(fail(), run());
8387 static assert(is(typeof(a
) == real));
8388 static assert(is(typeof(b
) == real));
8392 Determine if a symbol has a given
8393 $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8398 enum hasUDA(alias symbol
, alias attribute
) = getUDAs
!(symbol
, attribute
).length
!= 0;
8407 static assert(hasUDA
!(a
, "alpha"));
8408 static assert(!hasUDA
!(a
, S
));
8409 static assert(!hasUDA
!(a
, E
));
8412 static assert(!hasUDA
!(b
, "alpha"));
8413 static assert(!hasUDA
!(b
, S
));
8414 static assert(hasUDA
!(b
, E
));
8417 static assert(!hasUDA
!(c
, "alpha"));
8418 static assert(!hasUDA
!(c
, S
));
8419 static assert(hasUDA
!(c
, E
));
8422 static assert(!hasUDA
!(d
, "alpha"));
8423 static assert(hasUDA
!(d
, S
));
8424 static assert(hasUDA
!(d
, E
));
8427 static assert(!hasUDA
!(e
, "alpha"));
8428 static assert(hasUDA
!(e
, S
));
8429 static assert(!hasUDA
!(e
, S()));
8430 static assert(!hasUDA
!(e
, E
));
8433 static assert(!hasUDA
!(f
, "alpha"));
8434 static assert(hasUDA
!(f
, S
));
8435 static assert(hasUDA
!(f
, S()));
8436 static assert(!hasUDA
!(f
, E
));
8438 @
(S
, E
, "alpha") int g
;
8439 static assert(hasUDA
!(g
, "alpha"));
8440 static assert(hasUDA
!(g
, S
));
8441 static assert(hasUDA
!(g
, E
));
8444 static assert(hasUDA
!(h
, 100));
8446 struct Named
{ string name
; }
8448 @Named("abc") int i
;
8449 static assert(hasUDA
!(i
, Named
));
8450 static assert(hasUDA
!(i
, Named("abc")));
8451 static assert(!hasUDA
!(i
, Named("def")));
8459 @AttrT!int("answer", 42) int j
;
8460 static assert(hasUDA
!(j
, AttrT
));
8461 static assert(hasUDA
!(j
, AttrT
!int));
8462 static assert(!hasUDA
!(j
, AttrT
!string
));
8464 @AttrT!string("hello", "world") int k
;
8465 static assert(hasUDA
!(k
, AttrT
));
8466 static assert(!hasUDA
!(k
, AttrT
!int));
8467 static assert(hasUDA
!(k
, AttrT
!string
));
8469 struct FuncAttr(alias f
) { alias func
= f
; }
8470 static int fourtyTwo() { return 42; }
8471 static size_t
getLen(string s
) { return s
.length
; }
8473 @FuncAttr!getLen
int l
;
8474 static assert(hasUDA
!(l
, FuncAttr
));
8475 static assert(!hasUDA
!(l
, FuncAttr
!fourtyTwo
));
8476 static assert(hasUDA
!(l
, FuncAttr
!getLen
));
8477 static assert(!hasUDA
!(l
, FuncAttr
!fourtyTwo()));
8478 static assert(!hasUDA
!(l
, FuncAttr
!getLen()));
8480 @FuncAttr!getLen() int m
;
8481 static assert(hasUDA
!(m
, FuncAttr
));
8482 static assert(!hasUDA
!(m
, FuncAttr
!fourtyTwo
));
8483 static assert(hasUDA
!(m
, FuncAttr
!getLen
));
8484 static assert(!hasUDA
!(m
, FuncAttr
!fourtyTwo()));
8485 static assert(hasUDA
!(m
, FuncAttr
!getLen()));
8489 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8490 from the given symbol.
8492 If the UDA is a type, then any UDAs of the same type on the symbol will
8493 match. If the UDA is a template for a type, then any UDA which is an
8494 instantiation of that template will match. And if the UDA is a value,
8495 then any UDAs on the symbol which are equal to that value will match.
8500 template getUDAs(alias symbol
, alias attribute
)
8502 import std
.meta
: Filter
;
8504 alias getUDAs
= Filter
!(isDesiredUDA
!attribute
, __traits(getAttributes
, symbol
));
8516 @Attr("Answer", 42) int a
;
8517 static assert(getUDAs
!(a
, Attr
).length
== 1);
8518 static assert(getUDAs
!(a
, Attr
)[0].name
== "Answer");
8519 static assert(getUDAs
!(a
, Attr
)[0].value
== 42);
8521 @
(Attr("Answer", 42), "string", 9999) int b
;
8522 static assert(getUDAs
!(b
, Attr
).length
== 1);
8523 static assert(getUDAs
!(b
, Attr
)[0].name
== "Answer");
8524 static assert(getUDAs
!(b
, Attr
)[0].value
== 42);
8526 @Attr("Answer", 42) @Attr("Pi", 3) int c
;
8527 static assert(getUDAs
!(c
, Attr
).length
== 2);
8528 static assert(getUDAs
!(c
, Attr
)[0].name
== "Answer");
8529 static assert(getUDAs
!(c
, Attr
)[0].value
== 42);
8530 static assert(getUDAs
!(c
, Attr
)[1].name
== "Pi");
8531 static assert(getUDAs
!(c
, Attr
)[1].value
== 3);
8533 static assert(getUDAs
!(c
, Attr("Answer", 42)).length
== 1);
8534 static assert(getUDAs
!(c
, Attr("Answer", 42))[0].name
== "Answer");
8535 static assert(getUDAs
!(c
, Attr("Answer", 42))[0].value
== 42);
8537 static assert(getUDAs
!(c
, Attr("Answer", 99)).length
== 0);
8545 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d
;
8546 static assert(getUDAs
!(d
, AttrT
).length
== 2);
8547 static assert(getUDAs
!(d
, AttrT
)[0].name
== "Answer");
8548 static assert(getUDAs
!(d
, AttrT
)[0].value
== 42);
8549 static assert(getUDAs
!(d
, AttrT
)[1].name
== "Pi");
8550 static assert(getUDAs
!(d
, AttrT
)[1].value
== 3);
8552 static assert(getUDAs
!(d
, AttrT
!uint).length
== 1);
8553 static assert(getUDAs
!(d
, AttrT
!uint)[0].name
== "Answer");
8554 static assert(getUDAs
!(d
, AttrT
!uint)[0].value
== 42);
8556 static assert(getUDAs
!(d
, AttrT
!int).length
== 1);
8557 static assert(getUDAs
!(d
, AttrT
!int)[0].name
== "Pi");
8558 static assert(getUDAs
!(d
, AttrT
!int)[0].value
== 3);
8560 struct SimpleAttr
{}
8563 static assert(getUDAs
!(e
, SimpleAttr
).length
== 1);
8564 static assert(is(getUDAs
!(e
, SimpleAttr
)[0] == SimpleAttr
));
8566 @SimpleAttr() int f
;
8567 static assert(getUDAs
!(f
, SimpleAttr
).length
== 1);
8568 static assert(is(typeof(getUDAs
!(f
, SimpleAttr
)[0]) == SimpleAttr
));
8570 struct FuncAttr(alias f
) { alias func
= f
; }
8571 static int add42(int v
) { return v
+ 42; }
8572 static string
concat(string l
, string r
) { return l
~ r
; }
8574 @FuncAttr!add42
int g
;
8575 static assert(getUDAs
!(g
, FuncAttr
).length
== 1);
8576 static assert(getUDAs
!(g
, FuncAttr
)[0].func(5) == 47);
8578 static assert(getUDAs
!(g
, FuncAttr
!add42
).length
== 1);
8579 static assert(getUDAs
!(g
, FuncAttr
!add42
)[0].func(5) == 47);
8581 static assert(getUDAs
!(g
, FuncAttr
!add42()).length
== 0);
8583 static assert(getUDAs
!(g
, FuncAttr
!concat
).length
== 0);
8584 static assert(getUDAs
!(g
, FuncAttr
!concat()).length
== 0);
8586 @FuncAttr!add42() int h
;
8587 static assert(getUDAs
!(h
, FuncAttr
).length
== 1);
8588 static assert(getUDAs
!(h
, FuncAttr
)[0].func(5) == 47);
8590 static assert(getUDAs
!(h
, FuncAttr
!add42
).length
== 1);
8591 static assert(getUDAs
!(h
, FuncAttr
!add42
)[0].func(5) == 47);
8593 static assert(getUDAs
!(h
, FuncAttr
!add42()).length
== 1);
8594 static assert(getUDAs
!(h
, FuncAttr
!add42())[0].func(5) == 47);
8596 static assert(getUDAs
!(h
, FuncAttr
!concat
).length
== 0);
8597 static assert(getUDAs
!(h
, FuncAttr
!concat()).length
== 0);
8599 @
("alpha") @
(42) int i
;
8600 static assert(getUDAs
!(i
, "alpha").length
== 1);
8601 static assert(getUDAs
!(i
, "alpha")[0] == "alpha");
8603 static assert(getUDAs
!(i
, 42).length
== 1);
8604 static assert(getUDAs
!(i
, 42)[0] == 42);
8606 static assert(getUDAs
!(i
, 'c').length
== 0);
8609 private template isDesiredUDA(alias attribute
)
8611 template isDesiredUDA(alias toCheck
)
8613 static if (is(typeof(attribute
)) && !__traits(isTemplate
, attribute
))
8615 static if (__traits(compiles
, toCheck
== attribute
))
8616 enum isDesiredUDA
= toCheck
== attribute
;
8618 enum isDesiredUDA
= false;
8620 else static if (is(typeof(toCheck
)))
8622 static if (__traits(isTemplate
, attribute
))
8623 enum isDesiredUDA
= isInstanceOf
!(attribute
, typeof(toCheck
));
8625 enum isDesiredUDA
= is(typeof(toCheck
) == attribute
);
8627 else static if (__traits(isTemplate
, attribute
))
8628 enum isDesiredUDA
= isInstanceOf
!(attribute
, toCheck
);
8630 enum isDesiredUDA
= is(toCheck
== attribute
);
8636 symbol = The aggregate type or module to search
8637 attribute = The user-defined attribute to search for
8640 All symbols within `symbol` that have the given UDA `attribute`.
8643 This is not recursive; it will not search for symbols within symbols such as
8644 nested structs or unions.
8646 template getSymbolsByUDA(alias symbol
, alias attribute
)
8648 alias membersWithUDA
= getSymbolsByUDAImpl
!(symbol
, attribute
, __traits(allMembers
, symbol
));
8650 // if the symbol itself has the UDA, tack it on to the front of the list
8651 static if (hasUDA
!(symbol
, attribute
))
8652 alias getSymbolsByUDA
= AliasSeq
!(symbol
, membersWithUDA
);
8654 alias getSymbolsByUDA
= membersWithUDA
;
8667 static assert(getSymbolsByUDA
!(A
, Attr
).length
== 1);
8668 static assert(hasUDA
!(getSymbolsByUDA
!(A
, Attr
)[0], Attr
));
8680 @Attr void doStuff() {}
8681 void doOtherStuff() {}
8684 // Not found by getSymbolsByUDA
8689 // Finds both variables and functions with the attribute, but
8690 // doesn't include the variables and functions without it.
8691 static assert(getSymbolsByUDA
!(A
, Attr
).length
== 2);
8692 // Can access attributes on the symbols returned by getSymbolsByUDA.
8693 static assert(hasUDA
!(getSymbolsByUDA
!(A
, Attr
)[0], Attr
));
8694 static assert(hasUDA
!(getSymbolsByUDA
!(A
, Attr
)[1], Attr
));
8697 /// Finds multiple attributes
8700 static struct UDA
{ string name
; }
8712 // Finds both UDA attributes.
8713 static assert(getSymbolsByUDA
!(B
, UDA
).length
== 2);
8714 // Finds one `100` attribute.
8715 static assert(getSymbolsByUDA
!(B
, 100).length
== 1);
8716 // Can get the value of the UDA from the return value
8717 static assert(getUDAs
!(getSymbolsByUDA
!(B
, UDA
)[0], UDA
)[0].name
== "X");
8720 /// Checks for UDAs on the aggregate symbol itself
8723 static struct UDA
{ string name
; }
8732 static assert(getSymbolsByUDA
!(C
, UDA
).length
== 2);
8733 static assert(getSymbolsByUDA
!(C
, UDA
)[0].stringof
== "C");
8734 static assert(getSymbolsByUDA
!(C
, UDA
)[1].stringof
== "d");
8737 /// Finds nothing if there is no member with specific UDA
8740 static struct UDA
{ string name
; }
8747 static assert(getSymbolsByUDA
!(D
, UDA
).length
== 0);
8750 // https://issues.dlang.org/show_bug.cgi?id=18314
8760 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8762 //void foo()(string){}
8769 static assert(getSymbolsByUDA
!(A
, attr1
).length
== 2);
8770 static assert(getSymbolsByUDA
!(A
, attr2
).length
== 1);
8773 // getSymbolsByUDA fails if type has private members
8774 // https://issues.dlang.org/show_bug.cgi?id=15335
8777 // HasPrivateMembers has, well, private members, one of which has a UDA.
8778 import std
.internal
.test.uda
: Attr
, HasPrivateMembers
;
8779 // Trying access to private member from another file therefore we do not have access
8780 // for this otherwise we get deprecation warning - not visible from module
8781 // This line is commented because `__traits(getMember)` should also consider
8782 // private members; this is not currently the case, but the PR that
8783 // fixes `__traits(getMember)` is blocked by this specific test.
8784 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8785 static assert(hasUDA
!(getSymbolsByUDA
!(HasPrivateMembers
, Attr
)[0], Attr
));
8788 // getSymbolsByUDA works with structs but fails with classes
8789 // https://issues.dlang.org/show_bug.cgi?id=16387
8798 alias res
= getSymbolsByUDA
!(A
, Attr
);
8799 static assert(res
.length
== 1);
8800 static assert(res
[0].stringof
== "a");
8803 // getSymbolsByUDA fails on AliasSeq members
8804 // https://issues.dlang.org/show_bug.cgi?id=18884
8809 alias A
= AliasSeq
!(ulong, uint);
8812 static assert(is(getSymbolsByUDA
!(X
, X
) == AliasSeq
!()));
8815 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8816 // https://issues.dlang.org/show_bug.cgi?id=18624
8823 @Attr void a(int n
);
8828 static assert(getSymbolsByUDA
!(A
, Attr
).stringof
== "tuple(a, a, c)");
8831 // getSymbolsByUDA no longer works on modules
8832 // https://issues.dlang.org/show_bug.cgi?id=20054
8833 version (StdUnittest
)
8836 void issue20054() {}
8837 static assert(__traits(compiles
, getSymbolsByUDA
!(mixin(__MODULE__
), "Issue20054")));
8840 private template isAliasSeq(Args
...)
8842 static if (Args
.length
!= 1)
8843 enum isAliasSeq
= true;
8845 enum isAliasSeq
= false;
8848 private template getSymbolsByUDAImpl(alias symbol
, alias attribute
, names
...)
8850 import std
.meta
: Alias
, AliasSeq
, Filter
;
8851 static if (names
.length
== 0)
8853 alias getSymbolsByUDAImpl
= AliasSeq
!();
8857 alias tail
= getSymbolsByUDAImpl
!(symbol
, attribute
, names
[1 .. $]);
8859 // Filtering inaccessible members.
8860 static if (!__traits(compiles
, __traits(getMember
, symbol
, names
[0])))
8862 alias getSymbolsByUDAImpl
= tail
;
8866 alias member
= __traits(getMember
, symbol
, names
[0]);
8868 // Filtering not compiled members such as alias of basic types.
8869 static if (isAliasSeq
!member || isType
!member
)
8871 alias getSymbolsByUDAImpl
= tail
;
8873 // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
8874 else static if (__traits(getOverloads
, symbol
, names
[0], true).length
> 0)
8876 enum hasSpecificUDA(alias member
) = hasUDA
!(member
, attribute
);
8877 alias overloadsWithUDA
= Filter
!(hasSpecificUDA
, __traits(getOverloads
, symbol
, names
[0]));
8878 alias getSymbolsByUDAImpl
= AliasSeq
!(overloadsWithUDA
, tail
);
8880 else static if (hasUDA
!(member
, attribute
))
8882 alias getSymbolsByUDAImpl
= AliasSeq
!(member
, tail
);
8886 alias getSymbolsByUDAImpl
= tail
;
8893 Returns: `true` iff all types `Ts` are the same.
8895 enum bool allSameType(Ts
...) =
8897 static foreach (T
; Ts
[Ts
.length
> 1 .. $])
8898 static if (!is(Ts
[0] == T
))
8899 if (__ctfe
) // Dodge the "statement is unreachable" warning
8907 static assert(allSameType
!());
8908 static assert(allSameType
!(int));
8909 static assert(allSameType
!(int, int));
8910 static assert(allSameType
!(int, int, int));
8911 static assert(allSameType
!(float, float, float));
8912 static assert(!allSameType
!(int, double));
8913 static assert(!allSameType
!(int, float, double));
8914 static assert(!allSameType
!(int, float, double, real));
8915 static assert(!allSameType
!(short, int, float, double, real));
8919 Returns: `true` iff the type `T` can be tested in an $(D
8920 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
8922 enum ifTestable(T
, alias pred
= a
=> a
) = __traits(compiles
, { if (pred(T
.init
)) {} });
8931 T
opCast(T
)() const;
8934 static assert( ifTestable
!bool);
8935 static assert( ifTestable
!int);
8936 static assert( ifTestable
!(S1
*));
8937 static assert( ifTestable
!(typeof(null)));
8938 static assert( ifTestable
!(int[]));
8939 static assert( ifTestable
!(int[string
]));
8940 static assert( ifTestable
!S2
);
8941 static assert( ifTestable
!C
);
8942 static assert(!ifTestable
!S1
);
8947 import std
.meta
: AliasSeq
, allSatisfy
;
8948 static assert(allSatisfy
!(ifTestable
, AliasSeq
!(bool, int, float, double, string
)));
8949 struct BoolWrapper
{ bool value
; }
8950 static assert(!ifTestable
!(bool, a
=> BoolWrapper(a
)));
8954 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
8955 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
8958 * `true` if `X` is a type, `false` otherwise
8960 enum isType(alias X
) = is(X
);
8971 static assert(isType
!int);
8972 static assert(isType
!string
);
8973 static assert(isType
!(int[int]));
8974 static assert(isType
!S
);
8975 static assert(isType
!C
);
8976 static assert(isType
!I
);
8977 static assert(isType
!U
);
8981 static assert(!isType
!n
);
8982 static assert(!isType
!func
);
8983 static assert(!isType
!(S
.Test
));
8984 static assert(!isType
!(S
.Test
!()));
8988 * Detect whether symbol or type `X` is a function. This is different that finding
8989 * if a symbol is callable or satisfying `is(X == function)`, it finds
8990 * specifically if the symbol represents a normal function declaration, i.e.
8991 * not a delegate or a function pointer.
8994 * `true` if `X` is a function, `false` otherwise
8997 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
9000 template isFunction(alias X
)
9002 static if (is(typeof(&X
) U
: U
*) && is(U
== function) ||
9003 is(typeof(&X
) U
== delegate))
9005 // x is a (nested) function symbol.
9006 enum isFunction
= true;
9008 else static if (is(X T
))
9010 // x is a type. Take the type of it and examine.
9011 enum isFunction
= is(T
== function);
9014 enum isFunction
= false;
9020 static void func(){}
9021 static assert(isFunction
!func
);
9027 static assert(isFunction
!(S
.func
));
9031 * Detect whether `X` is a final method or class.
9034 * `true` if `X` is final, `false` otherwise
9036 template isFinal(alias X
)
9038 static if (is(X
== class))
9039 enum isFinal
= __traits(isFinalClass
, X
);
9040 else static if (isFunction
!X
)
9041 enum isFinal
= __traits(isFinalFunction
, X
);
9043 enum isFinal
= false;
9057 static assert(!isFinal
!(C
));
9058 static assert( isFinal
!(FC
));
9060 static assert(!isFinal
!(C
.nf
));
9061 static assert(!isFinal
!(C
.sf
));
9062 static assert( isFinal
!(C
.ff
));
9066 + Determines whether the type `S` can be copied.
9067 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9068 + Copying for structs can be disabled by using `@disable this(this)`.
9071 + S = The type to check.
9074 + `true` if `S` can be copied. `false` otherwise.
9076 enum isCopyable(S
) = __traits(isCopyable
, S
);
9081 struct S1
{} // Fine. Can be copied
9082 struct S2
{ this(this) {}} // Fine. Can be copied
9083 struct S3
{@disable this(this); } // Not fine. Copying is disabled.
9084 struct S4
{S3 s
;} // Not fine. A field has copying disabled.
9088 static assert( isCopyable
!S1
);
9089 static assert( isCopyable
!S2
);
9090 static assert(!isCopyable
!S3
);
9091 static assert(!isCopyable
!S4
);
9093 static assert(isCopyable
!C1
);
9094 static assert(isCopyable
!int);
9095 static assert(isCopyable
!(int[]));
9099 * The parameter type deduced by IFTI when an expression of type T is passed as
9100 * an argument to a template function.
9102 * For all types other than pointer and slice types, `DeducedParameterType!T`
9103 * is the same as `T`. For pointer and slice types, it is `T` with the
9104 * outer-most layer of qualifiers dropped.
9106 package(std
) template DeducedParameterType(T
)
9108 static if (is(T
== U
*, U
) ||
is(T
== U
[], U
))
9109 alias DeducedParameterType
= Unqual
!T
;
9111 alias DeducedParameterType
= T
;
9116 static assert(is(DeducedParameterType
!(const(int)) == const(int)));
9117 static assert(is(DeducedParameterType
!(const(int[2])) == const(int[2])));
9119 static assert(is(DeducedParameterType
!(const(int*)) == const(int)*));
9120 static assert(is(DeducedParameterType
!(const(int[])) == const(int)[]));
9125 static struct NoCopy
9127 @disable this(this);
9130 static assert(is(DeducedParameterType
!NoCopy
== NoCopy
));
9135 static assert(is(DeducedParameterType
!(inout(int[])) == inout(int)[]));
9138 private auto dip1000Test(int x
) {return *&x
;}
9139 // We don't use isSafe, because betterC client code needs to instantiate
9140 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9141 // __cmp of two strings, so using it would instantate that here instead. That
9142 // won't do because betterC compilations do not link the Phobos binary in.
9143 package(std
) enum dip1000Enabled
9144 = is(typeof(&dip1000Test
) : int function(int) @safe);