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