Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 16744: Add Typeof #5662

Merged
merged 1 commit into from
Jul 31, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
* $(LREF SharedConstOf)
* $(LREF ImmutableOf)
* $(LREF QualifierOf)
* $(LREF TypeOf)
* ))
* $(TR $(TD Categories of types) $(TD
* $(LREF allSameType)
Expand Down Expand Up @@ -5500,6 +5501,127 @@ template BuiltinTypeOf(T)
else static assert(0);
}

/*
A template designed to function in the same manner as the
built-in `typeof` utility. As it is a template, Typeof can be
passed around like any other symbol, unlike `typeof`.

Also, whereas `typeof` will not accept symbols that are already
types (e.g., `typeof(int)` will not compile), Typeof will accept
both values and types.

Params:
T = The symbol to take the type of. Can be either a type
or a value.

Returns:
The type of the given symbol. If the symbol is something that
does not have a valid type (such as a module name or an
expression that evaluates to the special `__error__` type),
an error will be raised at compile time.

Note:
If the given symbol is a template, the result type will be `void`.

*/
template Typeof(T...)
if (T.length == 1)
{
static if (__traits(isTemplate, T[0]))
alias Typeof = void;
else static if (is(T[0] TypeOfT0))
alias Typeof = TypeOfT0;
else static if (is(typeof(T[0]) TypeOfT0))
alias Typeof = TypeOfT0;
else
static assert(false, "Cannot take the type of " ~ T[0].stringof);
}

///
@safe unittest
{
//Types, values and expressions are accepted
assert(is(Typeof!1 == typeof(1)));
assert(is(Typeof!false == typeof(false)));
assert(is(Typeof!"" == string));

assert(is(Typeof!int == int));
assert(is(Typeof!bool == bool));
assert(is(Typeof!string == string));

assert(is(Typeof!(1 + 2 / 3) == typeof(1 + 2 / 3)));

struct S {}
assert(is(Typeof!(S()) == typeof(S())));
assert(is(Typeof!S == S));

class C {}
C c;
assert(is(Typeof!c == typeof(c)));
assert(is(Typeof!C == C));

//The type of a template is `void`
assert(is(Typeof!Typeof == typeof(Typeof)));
assert(is(Typeof!Typeof == void));

//Modules do not have a valid type
assert(!__traits(compiles, { alias _ = Typeof!(std.traits); }));
}

///
@safe unittest
{
import std.meta : AliasSeq, staticMap;

alias typesAndValues = AliasSeq!(int, false, char, "test");

//The built-in typeof cannot be passed to templates.
//The following will not compile
//alias justTypes = staticMap!(typeof, typeAndValues);

//But Typeof can
assert(is(staticMap!(Typeof, typesAndValues) == AliasSeq!(int, bool, char, string)));
}

@safe unittest
{
import std.meta : AliasSeq;

template testMatch(T...)
if (T.length == 1)
{
static if (is(T[0]))
enum testMatch = is(Typeof!(T[0]) == T[0]) && is(Typeof!(T[0].init) == typeof(T[0].init));
else static if (is(typeof(T[0])))
enum testMatch = is(Typeof!(T[0]) == typeof(T[0])) && is(Typeof!(typeof(T[0])) == typeof(T[0]));
else
enum testMatch = false;
}

struct TestS {}
class TestC {}

foreach (T; AliasSeq!(NumericTypeList,
ImaginaryTypeList,
ComplexTypeList,
CharTypeList,
TestS,
TestC))
{
static assert(testMatch!T);
static assert(testMatch!(T function(T)));
static assert(testMatch!(T delegate(T)));
static assert(testMatch!(T[]));
static assert(testMatch!(T[10]));
static assert(testMatch!(T[T]));
static assert(testMatch!(T*));
}

static assert(testMatch!null);
static assert(is(Typeof!void == void));
static assert(testMatch!Typeof);
}

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
// isSomething
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
Expand Down