module std.traits; enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real); template isIntegral(T) { static if (!__traits(isIntegral, T)) enum isIntegral = false; else static if (is(T U == enum)) enum isIntegral = isIntegral!U; else enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar. && !is(immutable T == immutable bool) && !is(T == __vector); } template isNumeric(T) { static if (!__traits(isArithmetic, T)) enum isNumeric = false; else static if (__traits(isFloating, T)) enum isNumeric = is(T : real); // Not __vector, imaginary, or complex. else static if (is(T U == enum)) enum isNumeric = isNumeric!U; else enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar. && !is(immutable T == immutable bool) && !is(T == __vector); } enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T) && is(T : real); enum hasMember(T, string name) = __traits(hasMember, T, name); enum bool isArray(T) = isStaticArray!T || isDynamicArray!T; enum bool isStaticArray(T) = __traits(isStaticArray, T); template isDynamicArray(T) { static if (is(T == U[], U)) enum bool isDynamicArray = true; else static if (is(T U == enum)) // BUG: isDynamicArray / isStaticArray considers enums // with appropriate base types as dynamic/static arrays // Retain old behaviour for now, see // https://github.com/dlang/phobos/pull/7574 enum bool isDynamicArray = isDynamicArray!U; else enum bool isDynamicArray = false; } enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs); enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; }); enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; }); enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...); template isInstanceOf(alias S, alias T) { enum impl(alias T : S!Args, Args...) = true; enum impl(alias T) = false; enum isInstanceOf = impl!T; } import core.internal.traits : CoreUnqual = Unqual; alias Unqual = CoreUnqual; @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} })); template isAggregateType(T) { static if (is(T == enum)) enum isAggregateType = isAggregateType!(OriginalType!T); else enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); } enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));