Add hasElaborate traits
This commit is contained in:
parent
c9a4a2f651
commit
2c064eb05b
@ -21,8 +21,9 @@ import std.algorithm.mutation;
|
|||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.meta;
|
import std.meta;
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Random-access range for the $(D_PSYMBOL Array).
|
* Random-access range for the $(D_PSYMBOL Array).
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.container.buffer;
|
module tanya.container.buffer;
|
||||||
|
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.container.entry;
|
module tanya.container.entry;
|
||||||
|
|
||||||
import std.traits;
|
import tanya.meta.trait;
|
||||||
import tanya.typecons;
|
import tanya.typecons;
|
||||||
|
|
||||||
package struct SEntry(T)
|
package struct SEntry(T)
|
||||||
|
@ -18,9 +18,9 @@ import std.algorithm.comparison;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.traits;
|
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward range for the $(D_PSYMBOL SList).
|
* Forward range for the $(D_PSYMBOL SList).
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
module tanya.container.queue;
|
module tanya.container.queue;
|
||||||
|
|
||||||
import core.exception;
|
import core.exception;
|
||||||
import std.traits;
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIFO queue.
|
* FIFO queue.
|
||||||
|
@ -16,10 +16,11 @@
|
|||||||
module tanya.container.set;
|
module tanya.container.set;
|
||||||
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.traits;
|
|
||||||
import tanya.container;
|
import tanya.container;
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bidirectional range that iterates over the $(D_PSYMBOL Set)'s values.
|
* Bidirectional range that iterates over the $(D_PSYMBOL Set)'s values.
|
||||||
|
@ -32,8 +32,9 @@ import std.algorithm.mutation;
|
|||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
|
import std.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
|
||||||
popFrontN, empty;
|
popFrontN, empty;
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
import tanya.range.array;
|
import tanya.range.array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,10 +14,11 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.format.conv;
|
module tanya.format.conv;
|
||||||
|
|
||||||
import std.traits;
|
|
||||||
import tanya.container.string;
|
import tanya.container.string;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.memory.op;
|
import tanya.memory.op;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown if a type conversion fails.
|
* Thrown if a type conversion fails.
|
||||||
|
@ -19,9 +19,9 @@ import std.algorithm.iteration;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
import tanya.memory.mmappool;
|
import tanya.memory.mmappool;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mixin generates common methods for classes and structs using
|
* The mixin generates common methods for classes and structs using
|
||||||
|
@ -22,8 +22,8 @@ import std.algorithm.comparison;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
private template Payload(T)
|
private template Payload(T)
|
||||||
{
|
{
|
||||||
|
@ -195,7 +195,7 @@ pure nothrow @safe @nogc unittest
|
|||||||
* T = A type.
|
* T = A type.
|
||||||
*
|
*
|
||||||
* Returns: Size of the type $(D_PARAM T).
|
* Returns: Size of the type $(D_PARAM T).
|
||||||
*/
|
*/
|
||||||
enum size_t sizeOf(T) = T.sizeof;
|
enum size_t sizeOf(T) = T.sizeof;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -391,7 +391,12 @@ version (TanyaPhobos)
|
|||||||
TemplateArgsOf,
|
TemplateArgsOf,
|
||||||
Parameters,
|
Parameters,
|
||||||
ParameterIdentifierTuple,
|
ParameterIdentifierTuple,
|
||||||
functionAttributes;
|
functionAttributes,
|
||||||
|
ParameterDefaults,
|
||||||
|
hasElaborateDestructor,
|
||||||
|
hasElaborateCopyConstructor,
|
||||||
|
hasElaborateAssign,
|
||||||
|
EnumMembers;
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@ -2330,3 +2335,295 @@ pure nothrow @safe @nogc unittest
|
|||||||
static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 0);
|
static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 0);
|
||||||
static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0);
|
static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a tuple with default values of the parameters to $(D_PARAM F).
|
||||||
|
*
|
||||||
|
* If a parameter doesn't have a default value, $(D_KEYWORD void) is returned.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* F = A function.
|
||||||
|
*
|
||||||
|
* Returns: Default values of the parameters to $(D_PARAM F).
|
||||||
|
*/
|
||||||
|
template ParameterDefaults(F...)
|
||||||
|
if (isCallable!F)
|
||||||
|
{
|
||||||
|
static if (is(FunctionTypeOf!F T == __parameters))
|
||||||
|
{
|
||||||
|
private template GetDefault(size_t i)
|
||||||
|
{
|
||||||
|
static if (i == T.length)
|
||||||
|
{
|
||||||
|
alias GetDefault = AliasSeq!();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum getDefault(T[i .. i + 1] name)
|
||||||
|
{
|
||||||
|
return name[0];
|
||||||
|
}
|
||||||
|
static if (is(typeof(getDefault())))
|
||||||
|
{
|
||||||
|
alias Default = Alias!(getDefault());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias Default = void;
|
||||||
|
}
|
||||||
|
alias GetDefault = AliasSeq!(Default, GetDefault!(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alias ParameterDefaults = GetDefault!0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
void func1(int k, uint b = 5, int[] = [1, 2]);
|
||||||
|
alias Defaults = ParameterDefaults!func1;
|
||||||
|
static assert(is(Defaults[0] == void));
|
||||||
|
static assert(Defaults[1 .. 3] == AliasSeq!(5, [1, 2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether $(D_PARAM T) has an elaborate destructor.
|
||||||
|
*
|
||||||
|
* Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
|
||||||
|
* length greater than`0` can have elaborate destructors, for all other types
|
||||||
|
* $(D_PSYMBOL hasElaborateDestructor) evaluates to $(D_KEYWORD false).
|
||||||
|
*
|
||||||
|
* An elaborate destructor is an explicitly defined destructor or one generated
|
||||||
|
* by the compiler. The compiler generates a destructor for a
|
||||||
|
* $(D_KEYWORD struct) if it has members with an elaborate destructor.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate destructor,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasElaborateDestructor(T)
|
||||||
|
{
|
||||||
|
static if (is(T E : E[L], size_t L))
|
||||||
|
{
|
||||||
|
enum bool hasElaborateDestructor = L > 0 && hasElaborateDestructor!E;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasElaborateDestructor = is(T == struct)
|
||||||
|
&& hasMember!(T, "__xdtor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
class C
|
||||||
|
{
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!hasElaborateDestructor!C);
|
||||||
|
|
||||||
|
static struct S
|
||||||
|
{
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static struct S1
|
||||||
|
{
|
||||||
|
S s;
|
||||||
|
}
|
||||||
|
static struct S2
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static assert(hasElaborateDestructor!S); // Explicit destructor.
|
||||||
|
static assert(hasElaborateDestructor!S1); // Compiler-generated destructor.
|
||||||
|
static assert(!hasElaborateDestructor!S2); // No destructor.
|
||||||
|
|
||||||
|
static assert(hasElaborateDestructor!(S[1]));
|
||||||
|
static assert(!hasElaborateDestructor!(S[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether $(D_PARAM T) has an elaborate postblit constructor.
|
||||||
|
*
|
||||||
|
* Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
|
||||||
|
* length greater than`0` can have elaborate postblit constructors, for all
|
||||||
|
* other types $(D_PSYMBOL hasElaborateCopyConstructor) evaluates to
|
||||||
|
* $(D_KEYWORD false).
|
||||||
|
*
|
||||||
|
* An elaborate postblit constructor is an explicitly defined postblit
|
||||||
|
* constructor or one generated by the compiler. The compiler generates a
|
||||||
|
* postblit constructor for a
|
||||||
|
* $(D_KEYWORD struct) if it has members with an elaborate postblit
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate postblit
|
||||||
|
* constructor, $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasElaborateCopyConstructor(T)
|
||||||
|
{
|
||||||
|
static if (is(T E : E[L], size_t L))
|
||||||
|
{
|
||||||
|
enum bool hasElaborateCopyConstructor = L > 0
|
||||||
|
&& hasElaborateCopyConstructor!E;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasElaborateCopyConstructor = is(T == struct)
|
||||||
|
&& hasMember!(T, "__xpostblit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(!hasElaborateCopyConstructor!int);
|
||||||
|
|
||||||
|
static struct S
|
||||||
|
{
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static struct S1
|
||||||
|
{
|
||||||
|
S s;
|
||||||
|
}
|
||||||
|
static struct S2
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static assert(hasElaborateCopyConstructor!S); // Explicit destructor.
|
||||||
|
static assert(hasElaborateCopyConstructor!S1); // Compiler-generated destructor.
|
||||||
|
static assert(!hasElaborateCopyConstructor!S2); // No destructor.
|
||||||
|
static assert(hasElaborateCopyConstructor!(S[1]));
|
||||||
|
static assert(!hasElaborateCopyConstructor!(S[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether $(D_PARAM T) has an elaborate assign.
|
||||||
|
*
|
||||||
|
* Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
|
||||||
|
* length greater than`0` can have an elaborate assign, for all
|
||||||
|
* other types $(D_PSYMBOL hasElaborateAssign) evaluates to $(D_KEYWORD false).
|
||||||
|
*
|
||||||
|
* An elaborate assign is defined with $(D_INLINECODE opAssign(typeof(this)))
|
||||||
|
* or $(D_INLINECODE opAssign(ref typeof(this))). An elaborate assign can be
|
||||||
|
* generated for a $(D_KEYWORD struct) by the compiler if one of the members of
|
||||||
|
* this $(D_KEYWORD struct) has an elaborate assign.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate assign,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasElaborateAssign(T)
|
||||||
|
{
|
||||||
|
static if (is(T E : E[L], size_t L))
|
||||||
|
{
|
||||||
|
enum bool hasElaborateAssign = L > 0 && hasElaborateAssign!E;
|
||||||
|
}
|
||||||
|
else static if (is(T == struct))
|
||||||
|
{
|
||||||
|
private enum bool valueAssign = is(typeof({ T.init.opAssign(T()); }));
|
||||||
|
enum bool hasElaborateAssign = valueAssign || is(typeof({
|
||||||
|
T s;
|
||||||
|
s.opAssign(s);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasElaborateAssign = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(!hasElaborateAssign!int);
|
||||||
|
|
||||||
|
static struct S1
|
||||||
|
{
|
||||||
|
void opAssign(S1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static struct S2
|
||||||
|
{
|
||||||
|
void opAssign(int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static struct S3
|
||||||
|
{
|
||||||
|
S1 s;
|
||||||
|
alias s this;
|
||||||
|
}
|
||||||
|
static assert(hasElaborateAssign!S1);
|
||||||
|
static assert(!hasElaborateAssign!(const S1));
|
||||||
|
static assert(hasElaborateAssign!(S1[1]));
|
||||||
|
static assert(!hasElaborateAssign!(S1[0]));
|
||||||
|
static assert(!hasElaborateAssign!S2);
|
||||||
|
static assert(hasElaborateAssign!S3);
|
||||||
|
|
||||||
|
static struct S4
|
||||||
|
{
|
||||||
|
void opAssign(S4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@disable this(this);
|
||||||
|
}
|
||||||
|
static assert(hasElaborateAssign!S4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all members of $(D_KEYWORD enum) $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* The members of $(D_PARAM T) are typed as $(D_PARAM T), not as a base type
|
||||||
|
* of the enum.
|
||||||
|
*
|
||||||
|
* $(D_PARAM EnumMembers) returns all members of $(D_PARAM T), also if there
|
||||||
|
* are some duplicates.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A $(D_KEYWORD enum).
|
||||||
|
*
|
||||||
|
* Returns: All members of $(D_PARAM T).
|
||||||
|
*/
|
||||||
|
template EnumMembers(T)
|
||||||
|
if (is(T == enum))
|
||||||
|
{
|
||||||
|
private template getEnumMembers(Args...)
|
||||||
|
{
|
||||||
|
static if (Args.length == 1)
|
||||||
|
{
|
||||||
|
enum T getEnumMembers = __traits(getMember, T, Args[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias getEnumMembers = AliasSeq!(__traits(getMember, T, Args[0]), getEnumMembers!(Args[1 .. $]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alias EnumMembers = getEnumMembers!(__traits(allMembers, T));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @nogc @safe unittest
|
||||||
|
{
|
||||||
|
enum E : int
|
||||||
|
{
|
||||||
|
one,
|
||||||
|
two,
|
||||||
|
three,
|
||||||
|
}
|
||||||
|
static assert([E.one, E.two, E.three] == [ EnumMembers!E ]);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user