summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-08-14 14:21:10 +0200
committerEugen Wissner <belka@caraus.de>2017-08-14 14:21:10 +0200
commitafd3c42c5fd29d98fbc31bc785ce4b62d4e89e97 (patch)
treede3f463f56db3c9db41d4ac909ea294a798a2d49
parent1d91bb4df91f1887b5d257434524cb5270683f46 (diff)
downloadtanya-afd3c42c5fd29d98fbc31bc785ce4b62d4e89e97.tar.gz
Add meta.traits module
-rw-r--r--source/tanya/meta/package.d1
-rw-r--r--source/tanya/meta/traits.d580
2 files changed, 581 insertions, 0 deletions
diff --git a/source/tanya/meta/package.d b/source/tanya/meta/package.d
index 9520c4b..5002849 100644
--- a/source/tanya/meta/package.d
+++ b/source/tanya/meta/package.d
@@ -14,4 +14,5 @@
*/
module tanya.meta;
+public import tanya.meta.traits;
public import tanya.meta.transform;
diff --git a/source/tanya/meta/traits.d b/source/tanya/meta/traits.d
new file mode 100644
index 0000000..6d34e4a
--- /dev/null
+++ b/source/tanya/meta/traits.d
@@ -0,0 +1,580 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Type traits.
+ *
+ * Templates in this module are used to obtain type information at compile
+ * time.
+ *
+ * Copyright: Eugene Wissner 2017.
+ * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
+ * Mozilla Public License, v. 2.0).
+ * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/meta/traits.d,
+ * tanya/meta/traits.d)
+ */
+module tanya.meta.traits;
+
+import tanya.meta.transform;
+
+/**
+ * Determines whether $(D_PARAM T) is a floating point type.
+ *
+ * Floating point types are:
+ * $(UL
+ * $(LI float)
+ * $(LI double)
+ * $(LI real)
+ * )
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isFloatingPoint(T) = is(Unqual!(OriginalType!T) == double)
+ || is(Unqual!(OriginalType!T) == float)
+ || is(Unqual!(OriginalType!T) == real);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isFloatingPoint!float);
+ static assert(isFloatingPoint!double);
+ static assert(isFloatingPoint!real);
+ static assert(isFloatingPoint!(const float));
+ static assert(isFloatingPoint!(shared float));
+ static assert(isFloatingPoint!(shared const float));
+ static assert(!isFloatingPoint!int);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a signed numeric type.
+ *
+ * Signed numeric types are:
+ * $(UL
+ * $(LI byte)
+ * $(LI short)
+ * $(LI int)
+ * $(LI long)
+ * $(LI float)
+ * $(LI double)
+ * $(LI real)
+ * )
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isUnsigned).
+ */
+enum bool isSigned(T) = is(Unqual!(OriginalType!T) == byte)
+ || is(Unqual!(OriginalType!T) == short)
+ || is(Unqual!(OriginalType!T) == int)
+ || is(Unqual!(OriginalType!T) == long)
+ || isFloatingPoint!T;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isSigned!byte);
+ static assert(isSigned!short);
+ static assert(isSigned!int);
+ static assert(isSigned!long);
+ static assert(isSigned!float);
+ static assert(isSigned!double);
+ static assert(isSigned!real);
+
+ static assert(!isSigned!ubyte);
+ static assert(!isSigned!ushort);
+ static assert(!isSigned!uint);
+ static assert(!isSigned!ulong);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is an unsigned numeric type.
+ *
+ * Unsigned numeric types are:
+ * $(UL
+ * $(LI ubyte)
+ * $(LI ushort)
+ * $(LI uint)
+ * $(LI ulong)
+ * )
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isSigned).
+ */
+enum bool isUnsigned(T) = is(Unqual!(OriginalType!T) == ubyte)
+ || is(Unqual!(OriginalType!T) == ushort)
+ || is(Unqual!(OriginalType!T) == uint)
+ || is(Unqual!(OriginalType!T) == ulong);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isUnsigned!ubyte);
+ static assert(isUnsigned!ushort);
+ static assert(isUnsigned!uint);
+ static assert(isUnsigned!ulong);
+
+ static assert(!isUnsigned!byte);
+ static assert(!isUnsigned!short);
+ static assert(!isUnsigned!int);
+ static assert(!isUnsigned!long);
+ static assert(!isUnsigned!float);
+ static assert(!isUnsigned!double);
+ static assert(!isUnsigned!real);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is an integral type.
+ *
+ * Integral types are:
+ * $(UL
+ * $(LI ubyte)
+ * $(LI ushort)
+ * $(LI uint)
+ * $(LI ulong)
+ * $(LI byte)
+ * $(LI short)
+ * $(LI int)
+ * $(LI long)
+ * )
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isIntegral(T) = isUnsigned!T
+ || is(Unqual!(OriginalType!T) == byte)
+ || is(Unqual!(OriginalType!T) == short)
+ || is(Unqual!(OriginalType!T) == int)
+ || is(Unqual!(OriginalType!T) == long);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isIntegral!ubyte);
+ static assert(isIntegral!byte);
+ static assert(!isIntegral!float);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a complex type.
+ *
+ * Complex types are:
+ * $(UL
+ * $(LI cfloat)
+ * $(LI ifloat)
+ * $(LI cdouble)
+ * $(LI idouble)
+ * $(LI creal)
+ * $(LI ireal)
+ * )
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isComplex(T) = is(Unqual!(OriginalType!T) == cfloat)
+ || is(Unqual!(OriginalType!T) == ifloat)
+ || is(Unqual!(OriginalType!T) == cdouble)
+ || is(Unqual!(OriginalType!T) == idouble)
+ || is(Unqual!(OriginalType!T) == creal)
+ || is(Unqual!(OriginalType!T) == ireal);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isComplex!cfloat);
+ static assert(isComplex!ifloat);
+ static assert(isComplex!cdouble);
+ static assert(isComplex!idouble);
+ static assert(isComplex!creal);
+ static assert(isComplex!ireal);
+
+ static assert(!isComplex!float);
+ static assert(!isComplex!double);
+ static assert(!isComplex!real);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a numeric (floating point, integral or
+ * complex) type.
+*
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isIntegral!T),
+ * $(D_PSYMBOL isFloatingPoint),
+ * $(D_PSYMBOL isComplex).
+ */
+enum bool isNumeric(T) = isIntegral!T || isFloatingPoint!T || isComplex!T;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ alias F = float;
+ static assert(isNumeric!F);
+ static assert(!isNumeric!bool);
+ static assert(!isNumeric!char);
+ static assert(!isNumeric!wchar);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a boolean type, i.e. $(D_KEYWORD bool).
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isBoolean(T) = is(Unqual!(OriginalType!T) == bool);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isBoolean!bool);
+ static assert(isBoolean!(shared const bool));
+ static assert(!isBoolean!(ubyte));
+ static assert(!isBoolean!(byte));
+
+ enum E : bool
+ {
+ t = true,
+ f = false,
+ }
+ static assert(isBoolean!E);
+
+ struct S1
+ {
+ bool b;
+ alias b this;
+ }
+ static assert(!isBoolean!S1);
+
+ struct S2
+ {
+ bool opCast(T : bool)()
+ {
+ return true;
+ }
+ }
+ static assert(!isBoolean!S2);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a character type.
+ *
+ * Character types are:
+ *
+ * $(UL
+ * $(LI char)
+ * $(LI wchar)
+ * $(LI dchar)
+ * )
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isSomeChar(T) = is(Unqual!(OriginalType!T) == char)
+ || is(Unqual!(OriginalType!T) == wchar)
+ || is(Unqual!(OriginalType!T) == dchar);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isSomeChar!char);
+ static assert(isSomeChar!wchar);
+ static assert(isSomeChar!dchar);
+
+ static assert(!isSomeChar!byte);
+ static assert(!isSomeChar!ubyte);
+ static assert(!isSomeChar!short);
+ static assert(!isSomeChar!ushort);
+ static assert(!isSomeChar!int);
+ static assert(!isSomeChar!uint);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a scalar type.
+ *
+ * Scalar types are numbers, booleans and characters.
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isNumeric),
+ * $(D_PSYMBOL isBoolean),
+ * $(D_PSYMBOL isSomeChar).
+ */
+enum bool isScalarType(T) = isNumeric!T || isBoolean!T || isSomeChar!T;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isScalarType!int);
+ static assert(!isScalarType!(int[]));
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a basic type.
+ *
+ * Basic types are scalar types and $(D_KEYWORD void).
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isScalarType).
+ */
+enum bool isBasicType(T) = isScalarType!T || is(T : void);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ struct S;
+ class C;
+ enum E : int
+ {
+ i = 0,
+ }
+
+ static assert(isBasicType!void);
+ static assert(isBasicType!(shared void));
+ static assert(isBasicType!E);
+ static assert(!isBasicType!(int*));
+ static assert(!isBasicType!(void function()));
+ static assert(!isBasicType!C);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a pointer type.
+ *
+ * Params:
+ * T = A type.
+ */
+template isPointer(T)
+{
+ static if (is(T U : U*))
+ {
+ enum bool isPointer = true;
+ }
+ else
+ {
+ enum bool isPointer = false;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isPointer!(bool*));
+ static assert(isPointer!(const bool*));
+ static assert(isPointer!(const shared bool*));
+ static assert(!isPointer!bool);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is an array type (dynamic or static, but
+ * not an associative one).
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isAssociativeArray).
+ */
+template isArray(T)
+{
+ static if (is(T U : U[]))
+ {
+ enum bool isArray = true;
+ }
+ else
+ {
+ enum bool isArray = false;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isArray!(bool[]));
+ static assert(isArray!(const bool[]));
+ static assert(isArray!(shared bool[]));
+ static assert(isArray!(bool[8]));
+ static assert(!isArray!bool);
+ static assert(!isArray!(bool[string]));
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a static array.
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isArray).
+ */
+template isStaticArray(T)
+{
+ static if (is(T U : U[L], size_t L))
+ {
+ enum bool isStaticArray = true;
+ }
+ else
+ {
+ enum bool isStaticArray = false;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isStaticArray!(bool[8]));
+ static assert(isStaticArray!(const bool[8]));
+ static assert(isStaticArray!(shared bool[8]));
+ static assert(!isStaticArray!(bool[]));
+ static assert(!isStaticArray!bool);
+ static assert(!isStaticArray!(bool[string]));
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a dynamic array.
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isArray).
+ */
+enum bool isDynamicArray(T) = isArray!T && !isStaticArray!T;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isDynamicArray!(bool[]));
+ static assert(isDynamicArray!(const bool[]));
+ static assert(isDynamicArray!(shared bool[]));
+ static assert(!isDynamicArray!(bool[8]));
+ static assert(!isDynamicArray!bool);
+ static assert(!isDynamicArray!(bool[string]));
+}
+
+/**
+ * Determines whether $(D_PARAM T) is an associative array.
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isArray).
+ */
+template isAssociativeArray(T)
+{
+ static if (is(T U : U[L], L))
+ {
+ enum bool isAssociativeArray = true;
+ }
+ else
+ {
+ enum bool isAssociativeArray = false;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isAssociativeArray!(bool[string]));
+ static assert(isAssociativeArray!(const bool[string]));
+ static assert(isAssociativeArray!(shared const bool[string]));
+ static assert(!isAssociativeArray!(bool[]));
+ static assert(!isAssociativeArray!(bool[8]));
+ static assert(!isAssociativeArray!bool);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is a built-in type.
+ *
+ * Built-in types are all basic types and arrays.
+ *
+ * Params:
+ * T = A type.
+ *
+ * See_Also: $(D_PSYMBOL isBasicType!T),
+ * $(D_PSYMBOL isArray),
+ * $(D_PSYMBOL isAssociativeArray).
+ */
+enum bool isBuiltinType(T) = isBasicType!T
+ || isArray!T
+ || isAssociativeArray!T;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(isBuiltinType!int);
+ static assert(isBuiltinType!(int[]));
+ static assert(isBuiltinType!(int[int]));
+ static assert(!isBuiltinType!(int*));
+}
+
+/**
+ * Determines whether $(D_PARAM T) is an aggregate type.
+ *
+ * Aggregate types are:
+ *
+ * $(UL
+ * $(LI $(D_KEYWORD struct)s)
+ * $(LI $(D_KEYWORD class)es)
+ * $(LI $(D_KEYWORD interface)s)
+ * $(LI $(D_KEYWORD union)s)
+ * )
+ *
+ * Params:
+ * T = A type.
+ */
+enum bool isAggregateType(T) = is(T == struct)
+ || is(T == class)
+ || is(T == interface)
+ || is(T == union);
+
+///
+pure nothrow @safe @nogc unittest
+{
+ struct S;
+ class C;
+ interface I;
+ union U;
+ enum E;
+
+ static assert(isAggregateType!S);
+ static assert(isAggregateType!C);
+ static assert(isAggregateType!I);
+ static assert(isAggregateType!U);
+ static assert(!isAggregateType!E);
+ static assert(!isAggregateType!void);
+}
+
+/**
+ * Determines whether $(D_PARAM T) is some type.
+ *
+ * Params:
+ * T = Some symbol.
+ */
+enum bool isType(alias T) = is(T);
+
+/// Ditto.
+enum bool isType(T) = true;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ class C;
+ enum E : bool;
+ union U;
+ struct T();
+
+ static assert(isType!C);
+ static assert(isType!E);
+ static assert(isType!U);
+ static assert(isType!void);
+ static assert(isType!int);
+ static assert(!isType!T);
+ static assert(isType!(T!()));
+ static assert(!isType!5);
+ static assert(!isType!(tanya.meta.traits));
+}