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.range.primitives;
|
||||
import std.meta;
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Random-access range for the $(D_PSYMBOL Array).
|
||||
|
@ -14,8 +14,8 @@
|
||||
*/
|
||||
module tanya.container.buffer;
|
||||
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
module tanya.container.entry;
|
||||
|
||||
import std.traits;
|
||||
import tanya.meta.trait;
|
||||
import tanya.typecons;
|
||||
|
||||
package struct SEntry(T)
|
||||
|
@ -18,9 +18,9 @@ import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.searching;
|
||||
import std.range.primitives;
|
||||
import std.traits;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* Forward range for the $(D_PSYMBOL SList).
|
||||
|
@ -15,10 +15,10 @@
|
||||
module tanya.container.queue;
|
||||
|
||||
import core.exception;
|
||||
import std.traits;
|
||||
import std.algorithm.mutation;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* FIFO queue.
|
||||
|
@ -16,10 +16,11 @@
|
||||
module tanya.container.set;
|
||||
|
||||
import std.algorithm.mutation;
|
||||
import std.traits;
|
||||
import tanya.container;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* 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.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
|
||||
popFrontN, empty;
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
import tanya.range.array;
|
||||
|
||||
/**
|
||||
|
@ -14,10 +14,11 @@
|
||||
*/
|
||||
module tanya.format.conv;
|
||||
|
||||
import std.traits;
|
||||
import tanya.container.string;
|
||||
import tanya.memory;
|
||||
import tanya.memory.op;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Thrown if a type conversion fails.
|
||||
|
@ -19,9 +19,9 @@ import std.algorithm.iteration;
|
||||
import std.algorithm.mutation;
|
||||
import std.conv;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
public import tanya.memory.allocator;
|
||||
import tanya.memory.mmappool;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* The mixin generates common methods for classes and structs using
|
||||
|
@ -22,8 +22,8 @@ import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.conv;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
private template Payload(T)
|
||||
{
|
||||
|
@ -391,7 +391,12 @@ version (TanyaPhobos)
|
||||
TemplateArgsOf,
|
||||
Parameters,
|
||||
ParameterIdentifierTuple,
|
||||
functionAttributes;
|
||||
functionAttributes,
|
||||
ParameterDefaults,
|
||||
hasElaborateDestructor,
|
||||
hasElaborateCopyConstructor,
|
||||
hasElaborateAssign,
|
||||
EnumMembers;
|
||||
}
|
||||
else:
|
||||
|
||||
@ -2330,3 +2335,295 @@ pure nothrow @safe @nogc unittest
|
||||
static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 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