Skip to content

Instantly share code, notes, and snippets.

@9rnsr
Last active June 13, 2019 06:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 9rnsr/4152297 to your computer and use it in GitHub Desktop.
Save 9rnsr/4152297 to your computer and use it in GitHub Desktop.
isType, isFunction, isPropertyFunction, isVariable, isEnum, isFinal
import std.traits;
/**
* Detect whether $(D X) is a type or not.
*/
template isType(X...) if (X.length == 1)
{
enum isType = is(X[0]);
}
unittest
{
struct S {
template Test() {}
}
class C {}
interface I {}
union U {}
static assert( isType!int);
static assert( isType!string);
static assert( isType!(int[int]));
static assert( isType!S);
static assert( isType!C);
static assert( isType!I);
static assert( isType!U);
int n;
void func(){}
static assert(!isType!n);
static assert(!isType!func);
static assert(!isType!(S.Test));
static assert(!isType!(S.Test!()));
static assert(!isType!(std));
static assert(!isType!(std.traits));
}
/**
* Detect whether symbol or type $(D X) is a function.
*/
template isFunction(X...) if (X.length == 1)
{
static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
is(typeof(&X[0]) U == delegate))
{
// x is a (nested) function symbol.
enum isFunction = true;
}
else static if (is(X[0] T))
{
// x is a type. Take the type of it and examine.
enum isFunction = is(T == function);
}
else
enum isFunction = false;
}
/**
* Detect whether symbol or type $(D X) is a function.
*/
template isPropertyFunction(X...) if (X.length == 1)
{
static if (isFunction!(X[0]))
{
alias fa = functionAttributes;
alias FA = FunctionAttribute;
enum isPropertyFunction = (fa!(FunctionTypeOf!(X[0])) & FA.property) != 0;
}
else
enum isPropertyFunction = false;
}
unittest
{
// for (nested) (property) function symbols
static void func(){}
static @property int prop(){ return 0; }
void nested_func(){}
@property int nested_prop(){ return 0; }
static assert( isFunction!func);
static assert( isFunction!prop);
static assert( isFunction!nested_func);
static assert( isFunction!nested_prop);
static assert(!isPropertyFunction!func);
static assert( isPropertyFunction!prop);
static assert(!isPropertyFunction!nested_func);
static assert( isPropertyFunction!nested_prop);
// for functino types
alias F = typeof(func);
alias P = SetFunctionAttributes!(F, "D", FunctionAttribute.property);
alias DG = typeof(&nested_func);
alias DP = typeof(&nested_prop);
static assert( isFunction!F);
static assert( isFunction!P);
static assert(!isFunction!DG); // DG is delegate type, not function type
static assert(!isFunction!DP); // DP is delegate type, not function type
static assert(!isPropertyFunction!F);
static assert( isPropertyFunction!P);
static assert(!isPropertyFunction!DG);
static assert(!isPropertyFunction!DP);
// other cases
int n;
struct S {}
static assert(!isFunction!int);
static assert(!isFunction!void);
static assert(!isFunction!n);
static assert(!isFunction!S);
static assert(!isFunction!std);
static assert(!isPropertyFunction!int);
static assert(!isPropertyFunction!void);
static assert(!isPropertyFunction!n);
static assert(!isPropertyFunction!S);
static assert(!isPropertyFunction!std);
enum E { x = 10 }
static assert(!isFunction!(E.x));
static assert(!isPropertyFunction!(E.x));
}
/**
* Detect whether symbol $(D X) is a run-time variable.
*/
template isVariable(X...) if (X.length == 1)
{
static if (!is(X[0]) &&
!is(typeof(X[0]) == void) &&
!isFunction!(X[0]))
{
enum isVariable =
is(typeof({ auto ptr = &X[0]; }))
|| is(typeof({ enum off = X[0].offsetof; }));
}
else
enum isVariable = false;
}
/**
* Detect whether $(D X) is an enum type, or manifest constant.
*/
template isEnum(X...) if (X.length == 1)
{
static if (is(X[0] == enum))
{
enum isEnum = true;
}
else static if (!is(X[0]) &&
!is(typeof(X[0]) == void) &&
!isFunction!(X[0]))
{
enum isEnum =
!is(typeof({ auto ptr = &X[0]; }))
&& !is(typeof({ enum off = X[0].offsetof; }));
}
else
enum isEnum = false;
}
version(unittest)
{
// for module variables
int mx;
immutable int ix = 0;
immutable int ix2; static this() { ix2 = 0; }
enum int ex = 0;
static assert( isVariable!mx);
static assert( isVariable!ix);
static assert( isVariable!ix2);
static assert(!isVariable!ex);
static assert(!isEnum!mx);
static assert(!isEnum!ix);
static assert(!isEnum!ix2);
static assert( isEnum!ex);
}
unittest
{
// for local variables
int my;
immutable int iy = 0;
enum int ey = 0;
static assert( isVariable!my);
static assert( isVariable!iy);
static assert(!isVariable!ey);
static assert(!isEnum!my);
static assert(!isEnum!iy);
static assert( isEnum!ey);
// for member variables
struct S {
int mz;
immutable int iz = 0;
immutable int iz2; this(int) { iz2 = 0; }
enum int ez = 0;
static int sval;
template Test() {}
}
static assert( isVariable!(S.mz));
static assert( isVariable!(S.iz));
static assert( isVariable!(S.iz2));
static assert(!isVariable!(S.ez));
static assert( isVariable!(S.sval));
static assert(!isEnum!(S.mz));
static assert(!isEnum!(S.iz));
static assert(!isEnum!(S.iz2));
static assert( isEnum!(S.ez));
static assert(!isEnum!(S.sval));
void function() fp;
void delegate() dg;
static assert( isVariable!(fp));
static assert( isVariable!(dg));
static assert(!isEnum!(fp));
static assert(!isEnum!(dg));
// for function and property function
void func(){}
@property int prop(){ return 0; }
static assert(!isVariable!func);
static assert(!isVariable!prop);
static assert(!isEnum!func);
static assert(!isEnum!prop);
// for aggregates
class C {}
interface I {}
union U {}
static assert(!isVariable!S);
static assert(!isVariable!C);
static assert(!isVariable!I);
static assert(!isVariable!U);
static assert(!isEnum!S);
static assert(!isEnum!C);
static assert(!isEnum!I);
static assert(!isEnum!U);
// for other symbols
static assert(!isVariable!(std)); // package
static assert(!isVariable!(std.traits)); // module
static assert(!isVariable!(S.Test)); // template
static assert(!isVariable!(S.Test!())); // template instance
static assert(!isEnum!(std)); // package
static assert(!isEnum!(std.traits)); // module
static assert(!isEnum!(S.Test)); // template
static assert(!isEnum!(S.Test!())); // template instance
enum E { x = 10 }
static assert(!isVariable!(E.x));
static assert( isEnum!(E.x));
}
unittest
{
enum E1 { a, b }
enum E2 : string { a = "A", b = "B" }
static assert( isEnum!E1);
static assert( isEnum!E2);
}
/**
* Detect whether $(D X) is a final function or class or not.
*/
template isFinal(X...) if (X.length == 1)
{
static if (is(X[0] == class))
{
enum isFinal = __traits(isFinalClass, X[0]);
}
else static if (isSomeFunction!X)
{
enum isFinal = __traits(isFinalFunction, X[0]);
}
else
enum isFinal = false;
}
unittest
{
class C
{
void nf() {}
static void sf() {}
final void ff() {}
}
final class FC { }
static assert(!isFinal!(C));
static assert( isFinal!(FC));
static assert(!isFinal!(C.nf));
static assert(!isFinal!(C.sf));
static assert( isFinal!(C.ff));
}
@9rnsr
Copy link
Author

9rnsr commented Dec 29, 2012

Updated. Merge isEnumType and isManifestConstant to isEnum.

@9rnsr
Copy link
Author

9rnsr commented Dec 29, 2012

Updated. Add isFinal from Issue 6614 - std.traits should have an isFinal template

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment