Add template-time Set and set-theoretic metafunctions
This commit is contained in:
parent
d38e33593e
commit
520bd399a3
@ -112,7 +112,7 @@ pure nothrow @safe @nogc unittest
|
||||
}
|
||||
|
||||
/**
|
||||
* Zips one or more $(D_PSYMBOL AliasTuple)s with $(D_PARAM f).
|
||||
* Zips one or more $(D_PSYMBOL Tuple)s with $(D_PARAM f).
|
||||
*
|
||||
* Given $(D_PARAM f) and tuples t1, t2, ..., tk, where tk[i] denotes the
|
||||
* $(I i)-th element of the tuple $(I k)-th tuple, $(D_PSYMBOL ZipWith)
|
||||
@ -137,7 +137,7 @@ pure nothrow @safe @nogc unittest
|
||||
* Params:
|
||||
* f = Some template that can be applied to the elements of
|
||||
* $(D_PARAM Tuples).
|
||||
* Tuples = $(D_PSYMBOL AliasTuple) instances.
|
||||
* Tuples = $(D_PSYMBOL Tuple) instances.
|
||||
*
|
||||
* Returns: A sequence, whose $(I i)-th element contains the $(I i)-th element
|
||||
* from each of the $(D_PARAM Tuples).
|
||||
@ -145,7 +145,7 @@ pure nothrow @safe @nogc unittest
|
||||
template ZipWith(alias f, Tuples...)
|
||||
if (Tuples.length > 0
|
||||
&& isTemplate!f
|
||||
&& allSatisfy!(ApplyLeft!(isInstanceOf, AliasTuple), Tuples))
|
||||
&& allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Tuples))
|
||||
{
|
||||
private template GetIth(size_t i, Args...)
|
||||
{
|
||||
@ -179,24 +179,24 @@ if (Tuples.length > 0
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias Result1 = ZipWith!(AliasSeq,
|
||||
AliasTuple!(1, 2),
|
||||
AliasTuple!(5, 6),
|
||||
AliasTuple!(9, 10));
|
||||
Tuple!(1, 2),
|
||||
Tuple!(5, 6),
|
||||
Tuple!(9, 10));
|
||||
static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
|
||||
|
||||
alias Result2 = ZipWith!(AliasSeq,
|
||||
AliasTuple!(1, 2, 3),
|
||||
AliasTuple!(4, 5));
|
||||
Tuple!(1, 2, 3),
|
||||
Tuple!(4, 5));
|
||||
static assert(Result2 == AliasSeq!(1, 4, 2, 5));
|
||||
|
||||
alias Result3 = ZipWith!(AliasSeq, AliasTuple!(), AliasTuple!(4, 5));
|
||||
alias Result3 = ZipWith!(AliasSeq, Tuple!(), Tuple!(4, 5));
|
||||
static assert(Result3.length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds a typed sequence of template parameters.
|
||||
*
|
||||
* Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL AliasTuple) doesn't unpack
|
||||
* Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL Tuple) doesn't unpack
|
||||
* its template parameters automatically. Consider:
|
||||
*
|
||||
* ---
|
||||
@ -211,7 +211,7 @@ pure nothrow @safe @nogc unittest
|
||||
* Using $(D_PSYMBOL AliasSeq) template `A` gets 4 parameters instead of 2,
|
||||
* because $(D_PSYMBOL AliasSeq) is just an alias for its template parameters.
|
||||
*
|
||||
* With $(D_PSYMBOL AliasTuple) it is possible to pass distinguishable
|
||||
* With $(D_PSYMBOL Tuple) it is possible to pass distinguishable
|
||||
* sequences of parameters to a template. So:
|
||||
*
|
||||
* ---
|
||||
@ -220,15 +220,15 @@ pure nothrow @safe @nogc unittest
|
||||
* static assert(Args.length == 2);
|
||||
* }
|
||||
*
|
||||
* alias BInstance = B!(AliasTuple!(int, uint), AliasTuple!(float, double));
|
||||
* alias BInstance = B!(Tuple!(int, uint), Tuple!(float, double));
|
||||
* ---
|
||||
*
|
||||
* Params:
|
||||
* Args = Elements of this $(D_PSYMBOL AliasTuple).
|
||||
* Args = Elements of this $(D_PSYMBOL Tuple).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL AliasSeq).
|
||||
*/
|
||||
template AliasTuple(Args...)
|
||||
template Tuple(Args...)
|
||||
{
|
||||
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
||||
alias Seq = Args;
|
||||
@ -240,9 +240,9 @@ template AliasTuple(Args...)
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias A = AliasTuple!(short);
|
||||
alias B = AliasTuple!(3, 8, 9);
|
||||
alias C = AliasTuple!(A, B);
|
||||
alias A = Tuple!(short);
|
||||
alias B = Tuple!(3, 8, 9);
|
||||
alias C = Tuple!(A, B);
|
||||
|
||||
static assert(C.length == 2);
|
||||
|
||||
@ -251,11 +251,175 @@ pure nothrow @safe @nogc unittest
|
||||
static assert(B.length == 3);
|
||||
static assert(B.Seq == AliasSeq!(3, 8, 9));
|
||||
|
||||
alias D = AliasTuple!();
|
||||
alias D = Tuple!();
|
||||
static assert(D.length == 0);
|
||||
static assert(is(D.Seq == AliasSeq!()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unordered sequence of unique aliases.
|
||||
*
|
||||
* $(D_PARAM Args) can contain duplicates, but they will be filteredout, so
|
||||
* $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
|
||||
* for determining if two items are equal.
|
||||
*
|
||||
* Params:
|
||||
* Args = Elements of this $(D_PSYMBOL Tuple).
|
||||
*/
|
||||
template Set(Args...)
|
||||
{
|
||||
/// Elements in this set as $(D_PSYMBOL AliasSeq).
|
||||
alias Seq = NoDuplicates!Args;
|
||||
|
||||
/// The length of the set.
|
||||
enum size_t length = Seq.length;
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias S1 = Set!(int, 5, 5, int, 4);
|
||||
static assert(S1.length == 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) containing all elements of the given
|
||||
* $(D_PARAM Sets).
|
||||
*
|
||||
* Params:
|
||||
* Sets = List of $(D_PSYMBOL Set) instances.
|
||||
*
|
||||
* Returns: Set-theoretic union of all $(D_PARAM Sets).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Union(Sets...)
|
||||
if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
|
||||
{
|
||||
private template Impl(Sets...)
|
||||
{
|
||||
static if (Sets.length == 0)
|
||||
{
|
||||
alias Impl = AliasSeq!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Impl = AliasSeq!(Sets[0].Seq, Impl!(Sets[1 .. $]));
|
||||
}
|
||||
}
|
||||
alias Union = Set!(Impl!Sets);
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Union!(S1, S2).Seq == AliasSeq!(2, 5, 8, 4, 3, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) that containing elements of
|
||||
* $(D_INLINECODE Sets[0]) that are also elements of all other sets in
|
||||
* $(D_PARAM Sets).
|
||||
*
|
||||
* Params:
|
||||
* Sets = List of $(D_PSYMBOL Set) instances.
|
||||
*
|
||||
* Returns: Set-theoretic intersection of all $(D_PARAM Sets).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Intersection(Sets...)
|
||||
if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
|
||||
{
|
||||
private template Impl(Args...)
|
||||
if (Args.length > 0)
|
||||
{
|
||||
alias Equal = ApplyLeft!(isEqual, Args[0]);
|
||||
static if (Args.length == 1)
|
||||
{
|
||||
enum bool Impl = true;
|
||||
}
|
||||
else static if (!anySatisfy!(Equal, Args[1].Seq))
|
||||
{
|
||||
enum bool Impl = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool Impl = Impl!(Args[0], Args[2 .. $]);
|
||||
}
|
||||
}
|
||||
|
||||
private enum bool FilterImpl(Args...) = Impl!(Args[0], Sets[1 .. $]);
|
||||
|
||||
static if (Sets.length == 0)
|
||||
{
|
||||
alias Intersection = Set!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Intersection = Set!(Filter!(FilterImpl, Sets[0].Seq));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Intersection!(S1, S2).Seq == AliasSeq!(8, 4));
|
||||
|
||||
static assert(Intersection!(S1).Seq == AliasSeq!(2, 5, 8, 4));
|
||||
static assert(Intersection!().length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) that contains all elements of
|
||||
* $(D_PARAM S1) that are not members of $(D_PARAM S2).
|
||||
*
|
||||
* Params:
|
||||
* S1 = A $(D_PSYMBOL Set).
|
||||
* S2 = A $(D_PSYMBOL Set).
|
||||
*
|
||||
* Returns: Set-theoretic difference of two sets $(D_PARAM S1) and
|
||||
* $(D_PARAM S2).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Difference(alias S1, alias S2)
|
||||
if (isInstanceOf!(Set, S1) && isInstanceOf!(Set, S2))
|
||||
{
|
||||
private template Impl(Args...)
|
||||
{
|
||||
alias Equal = ApplyLeft!(isEqual, Args[0]);
|
||||
enum bool Impl = !anySatisfy!(Equal, S2.Seq);
|
||||
}
|
||||
|
||||
static if (S1.length == 0)
|
||||
{
|
||||
alias Difference = Set!();
|
||||
}
|
||||
else static if (S2.length == 1)
|
||||
{
|
||||
alias Difference = S1;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Difference = Set!(Filter!(Impl, S1.Seq));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Difference!(S1, S2).Seq == AliasSeq!(2, 5));
|
||||
static assert(Difference!(S2, S1).Seq == AliasSeq!(3, 1));
|
||||
static assert(Difference!(S1, Set!()).Seq == AliasSeq!(2, 5, 8, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is less than or equal to
|
||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
||||
@ -451,6 +615,9 @@ pure nothrow @safe @nogc unittest
|
||||
* $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
|
||||
* considered to be not equal.
|
||||
*
|
||||
* If two items cannot be compared (for example comparing a type with a
|
||||
* number), they are considered not equal.
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
@ -461,7 +628,8 @@ template isEqual(Args...)
|
||||
if (Args.length == 2)
|
||||
{
|
||||
static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
|
||||
|| is(Args[0] == Args[1]))
|
||||
|| (isTypeTuple!Args && is(Args[0] == Args[1]))
|
||||
|| isSame!Args)
|
||||
{
|
||||
enum bool isEqual = true;
|
||||
}
|
||||
@ -475,6 +643,8 @@ if (Args.length == 2)
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(isEqual!(int, int));
|
||||
static assert(isEqual!(8, 8));
|
||||
static assert(!isEqual!(int, const(int)));
|
||||
static assert(!isEqual!(5, int));
|
||||
static assert(!isEqual!(5, 8));
|
||||
}
|
||||
|
@ -416,6 +416,9 @@ version (TanyaPhobos)
|
||||
EnumMembers,
|
||||
classInstanceAlignment,
|
||||
ifTestable,
|
||||
FunctionTypeOf,
|
||||
ReturnType,
|
||||
TemplateOf,
|
||||
isTypeTuple,
|
||||
isExpressions;
|
||||
}
|
||||
@ -1873,11 +1876,149 @@ pure nothrow @safe @nogc unittest
|
||||
}
|
||||
}
|
||||
|
||||
deprecated("Use tanya.meta.transform.FunctionTypeOf instead")
|
||||
alias FunctionTypeOf = tanya.meta.transform.FunctionTypeOf;
|
||||
/**
|
||||
* Params:
|
||||
* F = A function.
|
||||
*
|
||||
* Returns: Type of the function $(D_PARAM F).
|
||||
*/
|
||||
template FunctionTypeOf(F...)
|
||||
if (isCallable!F)
|
||||
{
|
||||
static if ((is(typeof(F[0]) T : T*) && is(T == function))
|
||||
|| (is(F[0] T : T*) && is(T == function))
|
||||
|| is(F[0] T == delegate)
|
||||
|| is(typeof(F[0]) T == delegate)
|
||||
|| is(F[0] T == function)
|
||||
|| is(typeof(&F[0]) T == delegate)
|
||||
|| (is(typeof(&F[0]) T : T*) && is(T == function)))
|
||||
{
|
||||
alias FunctionTypeOf = T;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall);
|
||||
}
|
||||
}
|
||||
|
||||
deprecated("Use tanya.meta.transform.ReturnType instead")
|
||||
alias ReturnType = tanya.meta.transform.ReturnType;
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(FunctionTypeOf!(void function()) == function));
|
||||
static assert(is(FunctionTypeOf!(() {}) == function));
|
||||
}
|
||||
|
||||
private pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(FunctionTypeOf!(void delegate()) == function));
|
||||
|
||||
static void staticFunc()
|
||||
{
|
||||
}
|
||||
auto functionPointer = &staticFunc;
|
||||
static assert(is(FunctionTypeOf!staticFunc == function));
|
||||
static assert(is(FunctionTypeOf!functionPointer == function));
|
||||
|
||||
void func()
|
||||
{
|
||||
}
|
||||
auto dg = &func;
|
||||
static assert(is(FunctionTypeOf!func == function));
|
||||
static assert(is(FunctionTypeOf!dg == function));
|
||||
|
||||
interface I
|
||||
{
|
||||
@property int prop();
|
||||
}
|
||||
static assert(is(FunctionTypeOf!(I.prop) == function));
|
||||
|
||||
struct S
|
||||
{
|
||||
void opCall()
|
||||
{
|
||||
}
|
||||
}
|
||||
class C
|
||||
{
|
||||
static void opCall()
|
||||
{
|
||||
}
|
||||
}
|
||||
S s;
|
||||
|
||||
static assert(is(FunctionTypeOf!s == function));
|
||||
static assert(is(FunctionTypeOf!C == function));
|
||||
static assert(is(FunctionTypeOf!S == function));
|
||||
}
|
||||
|
||||
private pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S2
|
||||
{
|
||||
@property int opCall()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
S2 s2;
|
||||
static assert(is(FunctionTypeOf!S2 == function));
|
||||
static assert(is(FunctionTypeOf!s2 == function));
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* F = A callable object.
|
||||
*
|
||||
* Returns: Return type of $(D_PARAM F).
|
||||
*/
|
||||
template ReturnType(F...)
|
||||
if (isCallable!F)
|
||||
{
|
||||
static if (is(FunctionTypeOf!(F[0]) T == return))
|
||||
{
|
||||
alias ReturnType = T;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(false, "Argument is not a callable");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(ReturnType!(int delegate()) == int));
|
||||
static assert(is(ReturnType!(bool function()) == bool));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the template $(D_PARAM T) is an instance of.
|
||||
*
|
||||
* Params:
|
||||
* T = Template instance.
|
||||
*
|
||||
* Returns: Template $(D_PARAM T) is an instance of.
|
||||
*/
|
||||
alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S(T)
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(S!int), S));
|
||||
|
||||
static void func(T)()
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(func!int), func));
|
||||
|
||||
template T(U)
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(T!int), T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mangled name of the symbol $(D_PARAM T).
|
||||
@ -2392,7 +2533,7 @@ if (isCallable!F)
|
||||
{
|
||||
attrs |= FunctionAttribute.shared_;
|
||||
}
|
||||
else static if (a == "system")
|
||||
else static if (a == "@system")
|
||||
{
|
||||
attrs |= FunctionAttribute.system;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
* Type transformations.
|
||||
*
|
||||
* Templates in this module can be used to modify type qualifiers or transform
|
||||
* types.
|
||||
* types. They take some type as argument and return a different type after
|
||||
* perfoming the specified transformation.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
@ -29,9 +30,6 @@ version (TanyaPhobos)
|
||||
KeyType,
|
||||
ValueType,
|
||||
Promoted,
|
||||
FunctionTypeOf,
|
||||
ReturnType,
|
||||
TemplateOf,
|
||||
InoutOf,
|
||||
ConstOf,
|
||||
SharedOf,
|
||||
@ -499,150 +497,6 @@ pure nothrow @safe @nogc unittest
|
||||
static assert(is(Promoted!(shared bool) == shared int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* F = A function.
|
||||
*
|
||||
* Returns: Type of the function $(D_PARAM F).
|
||||
*/
|
||||
template FunctionTypeOf(F...)
|
||||
if (isCallable!F)
|
||||
{
|
||||
static if ((is(typeof(F[0]) T : T*) && is(T == function))
|
||||
|| (is(F[0] T : T*) && is(T == function))
|
||||
|| is(F[0] T == delegate)
|
||||
|| is(typeof(F[0]) T == delegate)
|
||||
|| is(F[0] T == function)
|
||||
|| is(typeof(&F[0]) T == delegate)
|
||||
|| (is(typeof(&F[0]) T : T*) && is(T == function)))
|
||||
{
|
||||
alias FunctionTypeOf = T;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(FunctionTypeOf!(void function()) == function));
|
||||
static assert(is(FunctionTypeOf!(() {}) == function));
|
||||
}
|
||||
|
||||
private pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(FunctionTypeOf!(void delegate()) == function));
|
||||
|
||||
static void staticFunc()
|
||||
{
|
||||
}
|
||||
auto functionPointer = &staticFunc;
|
||||
static assert(is(FunctionTypeOf!staticFunc == function));
|
||||
static assert(is(FunctionTypeOf!functionPointer == function));
|
||||
|
||||
void func()
|
||||
{
|
||||
}
|
||||
auto dg = &func;
|
||||
static assert(is(FunctionTypeOf!func == function));
|
||||
static assert(is(FunctionTypeOf!dg == function));
|
||||
|
||||
interface I
|
||||
{
|
||||
@property int prop();
|
||||
}
|
||||
static assert(is(FunctionTypeOf!(I.prop) == function));
|
||||
|
||||
struct S
|
||||
{
|
||||
void opCall()
|
||||
{
|
||||
}
|
||||
}
|
||||
class C
|
||||
{
|
||||
static void opCall()
|
||||
{
|
||||
}
|
||||
}
|
||||
S s;
|
||||
|
||||
static assert(is(FunctionTypeOf!s == function));
|
||||
static assert(is(FunctionTypeOf!C == function));
|
||||
static assert(is(FunctionTypeOf!S == function));
|
||||
}
|
||||
|
||||
private pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S2
|
||||
{
|
||||
@property int opCall()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
S2 s2;
|
||||
static assert(is(FunctionTypeOf!S2 == function));
|
||||
static assert(is(FunctionTypeOf!s2 == function));
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* F = A callable object.
|
||||
*
|
||||
* Returns: Return type of $(D_PARAM F).
|
||||
*/
|
||||
template ReturnType(F...)
|
||||
if (isCallable!F)
|
||||
{
|
||||
static if (is(FunctionTypeOf!(F[0]) T == return))
|
||||
{
|
||||
alias ReturnType = T;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(false, "Argument is not a callable");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(ReturnType!(int delegate()) == int));
|
||||
static assert(is(ReturnType!(bool function()) == bool));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the template $(D_PARAM T) is an instance of.
|
||||
*
|
||||
* Params:
|
||||
* T = Template instance.
|
||||
*
|
||||
* Returns: Template $(D_PARAM T) is an instance of.
|
||||
*/
|
||||
alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S(T)
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(S!int), S));
|
||||
|
||||
static void func(T)()
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(func!int), func));
|
||||
|
||||
template T(U)
|
||||
{
|
||||
}
|
||||
static assert(isSame!(TemplateOf!(T!int), T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user