summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/tanya/container/array.d3
-rw-r--r--source/tanya/container/buffer.d2
-rw-r--r--source/tanya/container/entry.d2
-rw-r--r--source/tanya/container/list.d2
-rw-r--r--source/tanya/container/queue.d2
-rw-r--r--source/tanya/container/set.d3
-rw-r--r--source/tanya/container/string.d3
-rw-r--r--source/tanya/format/conv.d3
-rw-r--r--source/tanya/memory/package.d2
-rw-r--r--source/tanya/memory/smartref.d2
-rw-r--r--source/tanya/meta/trait.d301
11 files changed, 313 insertions, 12 deletions
diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d
index f884314..a13ec1e 100644
--- a/source/tanya/container/array.d
+++ b/source/tanya/container/array.d
@@ -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).
diff --git a/source/tanya/container/buffer.d b/source/tanya/container/buffer.d
index b78d971..e29e739 100644
--- a/source/tanya/container/buffer.d
+++ b/source/tanya/container/buffer.d
@@ -14,8 +14,8 @@
*/
module tanya.container.buffer;
-import std.traits;
import tanya.memory;
+import tanya.meta.trait;
version (unittest)
{
diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d
index 1aea478..75edbe8 100644
--- a/source/tanya/container/entry.d
+++ b/source/tanya/container/entry.d
@@ -14,7 +14,7 @@
*/
module tanya.container.entry;
-import std.traits;
+import tanya.meta.trait;
import tanya.typecons;
package struct SEntry(T)
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index fc87ee4..97228ab 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -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).
diff --git a/source/tanya/container/queue.d b/source/tanya/container/queue.d
index d9b5609..2b07a6a 100644
--- a/source/tanya/container/queue.d
+++ b/source/tanya/container/queue.d
@@ -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.
diff --git a/source/tanya/container/set.d b/source/tanya/container/set.d
index 15ce7a4..1c5e559 100644
--- a/source/tanya/container/set.d
+++ b/source/tanya/container/set.d
@@ -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.
diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d
index 68c258b..6918e29 100644
--- a/source/tanya/container/string.d
+++ b/source/tanya/container/string.d
@@ -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;
/**
diff --git a/source/tanya/format/conv.d b/source/tanya/format/conv.d
index 77b84e3..ac5754a 100644
--- a/source/tanya/format/conv.d
+++ b/source/tanya/format/conv.d
@@ -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.
diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d
index 385aff9..fcb7dfa 100644
--- a/source/tanya/memory/package.d
+++ b/source/tanya/memory/package.d
@@ -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
diff --git a/source/tanya/memory/smartref.d b/source/tanya/memory/smartref.d
index 4883109..e33abcd 100644
--- a/source/tanya/memory/smartref.d
+++ b/source/tanya/memory/smartref.d
@@ -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)
{
diff --git a/source/tanya/meta/trait.d b/source/tanya/meta/trait.d
index b4d4367..d6e2114 100644
--- a/source/tanya/meta/trait.d
+++ b/source/tanya/meta/trait.d
@@ -195,7 +195,7 @@ pure nothrow @safe @nogc unittest
* T = A type.
*
* Returns: Size of the type $(D_PARAM T).
- */
+ */
enum size_t sizeOf(T) = T.sizeof;
///
@@ -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 ]);
+}