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
|
* 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)
|
* $(I i)-th element of the tuple $(I k)-th tuple, $(D_PSYMBOL ZipWith)
|
||||||
@ -137,7 +137,7 @@ pure nothrow @safe @nogc unittest
|
|||||||
* Params:
|
* Params:
|
||||||
* f = Some template that can be applied to the elements of
|
* f = Some template that can be applied to the elements of
|
||||||
* $(D_PARAM Tuples).
|
* $(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
|
* Returns: A sequence, whose $(I i)-th element contains the $(I i)-th element
|
||||||
* from each of the $(D_PARAM Tuples).
|
* from each of the $(D_PARAM Tuples).
|
||||||
@ -145,7 +145,7 @@ pure nothrow @safe @nogc unittest
|
|||||||
template ZipWith(alias f, Tuples...)
|
template ZipWith(alias f, Tuples...)
|
||||||
if (Tuples.length > 0
|
if (Tuples.length > 0
|
||||||
&& isTemplate!f
|
&& isTemplate!f
|
||||||
&& allSatisfy!(ApplyLeft!(isInstanceOf, AliasTuple), Tuples))
|
&& allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Tuples))
|
||||||
{
|
{
|
||||||
private template GetIth(size_t i, Args...)
|
private template GetIth(size_t i, Args...)
|
||||||
{
|
{
|
||||||
@ -179,24 +179,24 @@ if (Tuples.length > 0
|
|||||||
pure nothrow @safe @nogc unittest
|
pure nothrow @safe @nogc unittest
|
||||||
{
|
{
|
||||||
alias Result1 = ZipWith!(AliasSeq,
|
alias Result1 = ZipWith!(AliasSeq,
|
||||||
AliasTuple!(1, 2),
|
Tuple!(1, 2),
|
||||||
AliasTuple!(5, 6),
|
Tuple!(5, 6),
|
||||||
AliasTuple!(9, 10));
|
Tuple!(9, 10));
|
||||||
static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
|
static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
|
||||||
|
|
||||||
alias Result2 = ZipWith!(AliasSeq,
|
alias Result2 = ZipWith!(AliasSeq,
|
||||||
AliasTuple!(1, 2, 3),
|
Tuple!(1, 2, 3),
|
||||||
AliasTuple!(4, 5));
|
Tuple!(4, 5));
|
||||||
static assert(Result2 == AliasSeq!(1, 4, 2, 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);
|
static assert(Result3.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a typed sequence of template parameters.
|
* 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:
|
* 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,
|
* Using $(D_PSYMBOL AliasSeq) template `A` gets 4 parameters instead of 2,
|
||||||
* because $(D_PSYMBOL AliasSeq) is just an alias for its template parameters.
|
* 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:
|
* sequences of parameters to a template. So:
|
||||||
*
|
*
|
||||||
* ---
|
* ---
|
||||||
@ -220,15 +220,15 @@ pure nothrow @safe @nogc unittest
|
|||||||
* static assert(Args.length == 2);
|
* static assert(Args.length == 2);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* alias BInstance = B!(AliasTuple!(int, uint), AliasTuple!(float, double));
|
* alias BInstance = B!(Tuple!(int, uint), Tuple!(float, double));
|
||||||
* ---
|
* ---
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* Args = Elements of this $(D_PSYMBOL AliasTuple).
|
* Args = Elements of this $(D_PSYMBOL Tuple).
|
||||||
*
|
*
|
||||||
* See_Also: $(D_PSYMBOL AliasSeq).
|
* See_Also: $(D_PSYMBOL AliasSeq).
|
||||||
*/
|
*/
|
||||||
template AliasTuple(Args...)
|
template Tuple(Args...)
|
||||||
{
|
{
|
||||||
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
||||||
alias Seq = Args;
|
alias Seq = Args;
|
||||||
@ -240,9 +240,9 @@ template AliasTuple(Args...)
|
|||||||
///
|
///
|
||||||
pure nothrow @safe @nogc unittest
|
pure nothrow @safe @nogc unittest
|
||||||
{
|
{
|
||||||
alias A = AliasTuple!(short);
|
alias A = Tuple!(short);
|
||||||
alias B = AliasTuple!(3, 8, 9);
|
alias B = Tuple!(3, 8, 9);
|
||||||
alias C = AliasTuple!(A, B);
|
alias C = Tuple!(A, B);
|
||||||
|
|
||||||
static assert(C.length == 2);
|
static assert(C.length == 2);
|
||||||
|
|
||||||
@ -251,11 +251,175 @@ pure nothrow @safe @nogc unittest
|
|||||||
static assert(B.length == 3);
|
static assert(B.length == 3);
|
||||||
static assert(B.Seq == AliasSeq!(3, 8, 9));
|
static assert(B.Seq == AliasSeq!(3, 8, 9));
|
||||||
|
|
||||||
alias D = AliasTuple!();
|
alias D = Tuple!();
|
||||||
static assert(D.length == 0);
|
static assert(D.length == 0);
|
||||||
static assert(is(D.Seq == AliasSeq!()));
|
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
|
* Tests whether $(D_INLINECODE Args[0]) is less than or equal to
|
||||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
* $(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
|
* $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
|
||||||
* considered to be not equal.
|
* 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:
|
* Params:
|
||||||
* Args = Two aliases to compare for equality.
|
* Args = Two aliases to compare for equality.
|
||||||
*
|
*
|
||||||
@ -461,7 +628,8 @@ template isEqual(Args...)
|
|||||||
if (Args.length == 2)
|
if (Args.length == 2)
|
||||||
{
|
{
|
||||||
static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
|
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;
|
enum bool isEqual = true;
|
||||||
}
|
}
|
||||||
@ -475,6 +643,8 @@ if (Args.length == 2)
|
|||||||
pure nothrow @safe @nogc unittest
|
pure nothrow @safe @nogc unittest
|
||||||
{
|
{
|
||||||
static assert(isEqual!(int, int));
|
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, int));
|
||||||
static assert(!isEqual!(5, 8));
|
static assert(!isEqual!(5, 8));
|
||||||
}
|
}
|
||||||
|
@ -416,6 +416,9 @@ version (TanyaPhobos)
|
|||||||
EnumMembers,
|
EnumMembers,
|
||||||
classInstanceAlignment,
|
classInstanceAlignment,
|
||||||
ifTestable,
|
ifTestable,
|
||||||
|
FunctionTypeOf,
|
||||||
|
ReturnType,
|
||||||
|
TemplateOf,
|
||||||
isTypeTuple,
|
isTypeTuple,
|
||||||
isExpressions;
|
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).
|
* Returns the mangled name of the symbol $(D_PARAM T).
|
||||||
@ -2392,7 +2533,7 @@ if (isCallable!F)
|
|||||||
{
|
{
|
||||||
attrs |= FunctionAttribute.shared_;
|
attrs |= FunctionAttribute.shared_;
|
||||||
}
|
}
|
||||||
else static if (a == "system")
|
else static if (a == "@system")
|
||||||
{
|
{
|
||||||
attrs |= FunctionAttribute.system;
|
attrs |= FunctionAttribute.system;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
* Type transformations.
|
* Type transformations.
|
||||||
*
|
*
|
||||||
* Templates in this module can be used to modify type qualifiers or transform
|
* 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.
|
* Copyright: Eugene Wissner 2017.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
@ -29,9 +30,6 @@ version (TanyaPhobos)
|
|||||||
KeyType,
|
KeyType,
|
||||||
ValueType,
|
ValueType,
|
||||||
Promoted,
|
Promoted,
|
||||||
FunctionTypeOf,
|
|
||||||
ReturnType,
|
|
||||||
TemplateOf,
|
|
||||||
InoutOf,
|
InoutOf,
|
||||||
ConstOf,
|
ConstOf,
|
||||||
SharedOf,
|
SharedOf,
|
||||||
@ -499,150 +497,6 @@ pure nothrow @safe @nogc unittest
|
|||||||
static assert(is(Promoted!(shared bool) == shared int));
|
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).
|
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user