From 3225380491775804acf93728a51ec3d9d68445a5 Mon Sep 17 00:00:00 2001 From: Jonathan M Davis Date: Fri, 7 Mar 2025 22:52:53 -0700 Subject: [PATCH] Add isType to phobos.sys.traits. This is a simple and straightforward trait. It just says whether the template argument is a type or not. It has the same functionality as the trait with the same name in std.traits. However, the implementation is different. The std.traits version just has an alias overload and uses an is expression, whereas it seemed like it would probably be more efficient to split the trait into two and have the kind of argument determine the result, since the compiler has to go through the work of deciding whether the argument matches already, though I don't know enough about the compiler implementation to know for sure that this implementation is better. Either way, it can be changed later if it's determined that the std.traits implementation is better. --- phobos/sys/traits.d | 80 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/phobos/sys/traits.d b/phobos/sys/traits.d index 84dfe649c4b..2036bbe49d3 100644 --- a/phobos/sys/traits.d +++ b/phobos/sys/traits.d @@ -60,6 +60,7 @@ $(LREF isPointer) $(LREF isSignedInteger) $(LREF isStaticArray) + $(LREF isType) $(LREF isUnsignedInteger) )) $(TR $(TD Aggregate Type traits) $(TD @@ -1367,6 +1368,85 @@ enum isPointer(T) = is(T == U*, U); } } +/++ + Evaluates to $(D true) if given a type and $(D false) for all other symbols. + + This is equivalent to $(D is(T)), but some people may find using a named + trait to be clearer, and it can be used in conjunction with templates that + take a template predicate (such as those in phobos.sys.meta), which can't + be done with naked is expressions. + + See_Also: + $(DDSUBLINK dlang.org/spec/expression.html, is-type, Spec on the related is expression) + +/ +enum isType(T) = true; + +/// Ditto +enum isType(alias sym) = false; + +/// +@safe unittest +{ + static assert( isType!int); + static assert( isType!(int[])); + static assert( isType!string); + static assert( isType!(int[int])); + static assert( isType!(ubyte*)); + static assert( isType!void); + + int i; + static assert(!isType!i); + static assert( isType!(typeof(i))); + + struct S {} + static assert( isType!S); + static assert(!isType!(S.init)); + + class C {} + static assert( isType!C); + static assert(!isType!(C.init)); + + interface I {} + static assert( isType!I); + static assert(!isType!(I.init)); + + union U {} + static assert( isType!U); + static assert(!isType!(U.init)); + + static void func() {} + static assert(!isType!func); + static assert( isType!(typeof(func))); + + void funcWithContext() { ++i; } + static assert(!isType!funcWithContext); + static assert( isType!(typeof(funcWithContext))); + + int function() funcPtr; + static assert(!isType!funcPtr); + static assert( isType!(typeof(funcPtr))); + + int delegate() del; + static assert(!isType!del); + static assert( isType!(typeof(del))); + + template Templ() {} + static assert(!isType!Templ); + static assert(!isType!(Templ!())); + + template TemplWithType() + { + struct S {} + } + static assert(!isType!TemplWithType); + static assert(!isType!(TemplWithType!())); + static assert( isType!(TemplWithType!().S)); + + struct TemplType() {} + static assert(!isType!TemplType); + static assert( isType!(TemplType!())); +} + /++ Evaluates to $(D true) if the given type or symbol is an instantiation of the given template.