Remove meta.transform duplicating Phobos

This commit is contained in:
2025-08-24 13:01:12 +02:00
parent 1857d59375
commit 260b131222
23 changed files with 25 additions and 1904 deletions

View File

@@ -18,8 +18,9 @@
*/
module tanya.meta.metafunction;
import std.traits : Unqual;
import std.meta : NoDuplicates;
import tanya.meta.trait;
import tanya.meta.transform;
/**
* Finds the minimum value in $(D_PARAM Args) according to $(D_PARAM pred).
@@ -1601,145 +1602,6 @@ if (__traits(isTemplate, pred))
static assert(is(Filter!(isIntegral, Given) == AliasSeq!(int, uint)));
}
/**
* Removes all duplicates from the alias sequence $(D_PARAM L).
*
* Params:
* L = Alias sequence.
*
* Returns: $(D_PARAM L) containing only unique items.
*/
template NoDuplicates(L...)
{
static if (L.length == 0)
{
alias NoDuplicates = AliasSeq!();
}
else
{
private alias Rest = NoDuplicates!(EraseAll!(L[0], L[1 .. $]));
alias NoDuplicates = AliasSeq!(L[0], Rest);
}
}
///
@nogc nothrow pure @safe unittest
{
alias Given = AliasSeq!(int, uint, int, short, short, uint);
static assert(is(NoDuplicates!Given == AliasSeq!(int, uint, short)));
}
/**
* Converts an input range $(D_PARAM range) into an alias sequence.
*
* Params:
* range = Input range.
*
* Returns: Alias sequence with items from $(D_PARAM range).
*/
template aliasSeqOf(alias range)
{
static if (isArray!(typeof(range)))
{
static if (range.length == 0)
{
alias aliasSeqOf = AliasSeq!();
}
else
{
alias aliasSeqOf = AliasSeq!(range[0], aliasSeqOf!(range[1 .. $]));
}
}
else
{
ReturnType!(typeof(&range.front))[] toArray(typeof(range) range)
{
typeof(return) result;
foreach (r; range)
{
result ~= r;
}
return result;
}
alias aliasSeqOf = aliasSeqOf!(toArray(range));
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(aliasSeqOf!([0, 1, 2, 3]) == AliasSeq!(0, 1, 2, 3));
}
/**
* Produces a alias sequence consisting of every $(D_PARAM n)th element of
* $(D_PARAM Args), starting with the first.
*
* Params:
* n = Step.
* Args = The items to stride.
*
* Returns: Alias sequence of every $(D_PARAM n)th element of $(D_PARAM Args).
*/
template Stride(size_t n, Args...)
if (n > 0)
{
static if (Args.length > n)
{
alias Stride = AliasSeq!(Args[0], Stride!(n, Args[n .. $]));
}
else static if (Args.length > 0)
{
alias Stride = AliasSeq!(Args[0]);
}
else
{
alias Stride = AliasSeq!();
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(Stride!(3, 1, 2, 3, 4, 5, 6, 7, 8) == AliasSeq!(1, 4, 7));
static assert(Stride!(2, 1, 2, 3) == AliasSeq!(1, 3));
static assert(Stride!(2, 1, 2) == AliasSeq!(1));
static assert(Stride!(2, 1) == AliasSeq!(1));
static assert(Stride!(1, 1, 2, 3) == AliasSeq!(1, 2, 3));
static assert(is(Stride!3 == AliasSeq!()));
}
/**
* Aliases itself to $(D_INLINECODE T[0]) if $(D_PARAM cond) is $(D_KEYWORD true),
* to $(D_INLINECODE T[1]) if $(D_KEYWORD false).
*
* Params:
* cond = Template predicate.
* T = Two arguments.
*
* Returns: $(D_INLINECODE T[0]) if $(D_PARAM cond) is $(D_KEYWORD true),
* $(D_INLINECODE T[1]) otherwise.
*/
template Select(bool cond, T...)
if (T.length == 2)
{
static if (cond)
{
alias Select = T[0];
}
else
{
alias Select = T[1];
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(Select!(true, int, float) == int));
static assert(is(Select!(false, int, float) == float));
}
/**
* Attaches a numeric index to each element from $(D_PARAM Args).
*

View File

@@ -20,4 +20,3 @@ module tanya.meta;
public import tanya.meta.metafunction;
public import tanya.meta.trait;
public import tanya.meta.transform;

File diff suppressed because it is too large Load Diff

View File

@@ -1,504 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Type transformations.
*
* Templates in this module can be used to modify type qualifiers or transform
* types. They take some type as argument and return a different type after
* perfoming the specified transformation.
*
* Copyright: Eugene Wissner 2017-2025.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/transform.d,
* tanya/meta/transform.d)
*/
module tanya.meta.transform;
import tanya.meta.metafunction;
import tanya.meta.trait;
/**
* Removes any type qualifiers from $(D_PARAM T).
*
* Removed qualifiers are:
* $(UL
* $(LI const)
* $(LI immutable)
* $(LI inout)
* $(LI shared)
* )
* and combinations of these.
*
* If the type $(D_PARAM T) doesn't have any qualifieres,
* $(D_INLINECODE Unqual!T) becomes an alias for $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_PARAM T) without any type qualifiers.
*/
template Unqual(T)
{
static if (is(T U == shared const U)
|| is(T U == shared inout U)
|| is(T U == shared inout const U)
|| is(T U == inout const U)
|| is(T U == const U)
|| is(T U == immutable U)
|| is(T U == inout U)
|| is(T U == shared U))
{
alias Unqual = U;
}
else
{
alias Unqual = T;
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(Unqual!bool == bool));
static assert(is(Unqual!(immutable bool) == bool));
static assert(is(Unqual!(inout bool) == bool));
static assert(is(Unqual!(inout const bool) == bool));
static assert(is(Unqual!(shared bool) == bool));
static assert(is(Unqual!(shared const bool) == bool));
static assert(is(Unqual!(shared inout const bool) == bool));
}
/**
* If $(D_PARAM T) is an $(D_KEYWORD enum), $(D_INLINECODE OriginalType!T)
* evaluates to the most base type of that $(D_KEYWORD enum) and to
* $(D_PARAM T) otherwise.
*
* Params:
* T = A type.
*
* Returns: Base type of the $(D_KEYWORD enum) $(D_PARAM T) or $(D_PARAM T)
* itself.
*/
template OriginalType(T)
{
static if (is(T U == enum))
{
alias OriginalType = OriginalType!U;
}
else
{
alias OriginalType = T;
}
}
///
@nogc nothrow pure @safe unittest
{
enum E1 : const(int)
{
n = 0,
}
enum E2 : bool
{
t = true,
}
enum E3 : E2
{
t = E2.t,
}
enum E4 : const(E2)
{
t = E2.t,
}
static assert(is(OriginalType!E1 == const int));
static assert(is(OriginalType!E2 == bool));
static assert(is(OriginalType!E3 == bool));
static assert(is(OriginalType!E4 == bool));
static assert(is(OriginalType!(const E4) == bool));
}
/**
* Copies constness of $(D_PARAM From) to $(D_PARAM To).
*
* The following type qualifiers affect the constness and hence are copied:
* $(UL
* $(LI const)
* $(LI immutable)
* $(LI inout)
* $(LI inout const)
* )
*
* Params:
* From = Source type.
* To = Target type.
*
* Returns: $(D_PARAM To) with the constness of $(D_PARAM From).
*/
template CopyConstness(From, To)
{
static if (is(From T == immutable T))
{
alias CopyConstness = immutable To;
}
else static if (is(From T == const T) || is(From T == shared const T))
{
alias CopyConstness = const To;
}
else static if (is(From T == inout T) || is(From T == shared inout T))
{
alias CopyConstness = inout To;
}
else static if (is(From T == inout const T)
|| is(From T == shared inout const T))
{
alias CopyConstness = inout const To;
}
else
{
alias CopyConstness = To;
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(CopyConstness!(int, char) == char));
static assert(is(CopyConstness!(const int, char) == const char));
static assert(is(CopyConstness!(immutable int, char) == immutable char));
static assert(is(CopyConstness!(inout int, char) == inout char));
static assert(is(CopyConstness!(inout const int, char) == inout const char));
static assert(is(CopyConstness!(shared int, char) == char));
static assert(is(CopyConstness!(shared const int, char) == const char));
static assert(is(CopyConstness!(shared inout int, char) == inout char));
static assert(is(CopyConstness!(shared inout const int, char) == inout const char));
static assert(is(CopyConstness!(const int, shared char) == shared const char));
static assert(is(CopyConstness!(const int, immutable char) == immutable char));
static assert(is(CopyConstness!(immutable int, const char) == immutable char));
}
/**
* Retrieves the target type `U` of a pointer `U*`.
*
* Params:
* T = Pointer type.
*
* Returns: Pointer target type.
*/
template PointerTarget(T)
{
static if (is(T U : U*))
{
alias PointerTarget = U;
}
else
{
static assert(T.stringof ~ " isn't a pointer type");
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(PointerTarget!(bool*) == bool));
static assert(is(PointerTarget!(const bool*) == const bool));
static assert(is(PointerTarget!(const shared bool*) == const shared bool));
static assert(!is(PointerTarget!bool));
}
/**
* Params:
* T = The type of the associative array.
*
* Returns: The key type of the associative array $(D_PARAM T).
*/
template KeyType(T)
{
static if (is(T V : V[K], K))
{
alias KeyType = K;
}
else
{
static assert(false, T.stringof ~ " isn't an associative array");
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(KeyType!(int[string]) == string));
static assert(!is(KeyType!(int[15])));
}
/**
* Params:
* T = The type of the associative array.
*
* Returns: The value type of the associative array $(D_PARAM T).
*/
template ValueType(T)
{
static if (is(T V : V[K], K))
{
alias ValueType = V;
}
else
{
static assert(false, T.stringof ~ " isn't an associative array");
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(ValueType!(int[string]) == int));
static assert(!is(ValueType!(int[15])));
}
/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE inout(T)).
*/
alias InoutOf(T) = inout(T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(InoutOf!int == inout int));
}
/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE inout(T)).
*/
alias ConstOf(T) = const(T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(ConstOf!int == const int));
}
/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE inout(T)).
*/
alias SharedOf(T) = shared(T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(SharedOf!int == shared int));
}
/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE inout(T)).
*/
alias SharedInoutOf(T) = shared(inout T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(SharedInoutOf!int == shared inout int));
}
/**
* Adds $(D_KEYWORD shared const) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE shared(const T)).
*/
alias SharedConstOf(T) = shared(const T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(SharedConstOf!int == shared const int));
}
/**
* Adds $(D_KEYWORD immutable) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE immutable(T)).
*/
alias ImmutableOf(T) = immutable(T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(ImmutableOf!int == immutable int));
}
/**
* Adds $(D_KEYWORD inout const) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE inout(const T)).
*/
alias InoutConstOf(T) = inout(const T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(InoutConstOf!int == inout const int));
}
/**
* Adds $(D_KEYWORD shared inout const) qualifier to the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: $(D_INLINECODE shared(inout const T)).
*/
alias SharedInoutConstOf(T) = shared(inout const T);
///
@nogc nothrow pure @safe unittest
{
static assert(is(SharedInoutConstOf!int == shared inout const int));
}
/**
* Determines the type of $(D_PARAM T). If $(D_PARAM T) is already a type,
* $(D_PSYMBOL TypeOf) aliases itself to $(D_PARAM T).
*
* $(D_PSYMBOL TypeOf) evaluates to $(D_KEYWORD void) for template arguments.
*
* The symbols that don't have a type and aren't types cannot be used as
* arguments to $(D_PSYMBOL TypeOf).
*
* Params:
* T = Expression, type or template.
*
* Returns: The type of $(D_PARAM T).
*/
alias TypeOf(T) = T;
/// ditto
template TypeOf(alias T)
if (isExpressions!T || __traits(isTemplate, T))
{
alias TypeOf = typeof(T);
}
///
@nogc nothrow pure @safe unittest
{
struct S(T)
{
}
static assert(is(TypeOf!S == void));
static assert(is(TypeOf!int == int));
static assert(is(TypeOf!true == bool));
static assert(!is(TypeOf!(tanya.meta)));
}
/**
* Finds the type with the smallest size in the $(D_PARAM Args) list. If
* several types have the same type, the leftmost is returned.
*
* Params:
* Args = Type list.
*
* Returns: The smallest type.
*
* See_Also: $(D_PSYMBOL Largest).
*/
template Smallest(Args...)
if (Args.length >= 1)
{
static assert(is(Args[0]), T.stringof ~ " doesn't have .sizeof property");
static if (Args.length == 1)
{
alias Smallest = Args[0];
}
else static if (Smallest!(Args[1 .. $]).sizeof < Args[0].sizeof)
{
alias Smallest = Smallest!(Args[1 .. $]);
}
else
{
alias Smallest = Args[0];
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(Smallest!(int, ushort, uint, short) == ushort));
static assert(is(Smallest!(short) == short));
static assert(is(Smallest!(ubyte[8], ubyte[5]) == ubyte[5]));
static assert(!is(Smallest!(short, 5)));
}
/**
* Finds the type with the largest size in the $(D_PARAM Args) list. If several
* types have the same type, the leftmost is returned.
*
* Params:
* Args = Type list.
*
* Returns: The largest type.
*
* See_Also: $(D_PSYMBOL Smallest).
*/
template Largest(Args...)
if (Args.length >= 1)
{
static assert(is(Args[0]), T.stringof ~ " doesn't have .sizeof property");
static if (Args.length == 1)
{
alias Largest = Args[0];
}
else static if (Largest!(Args[1 .. $]).sizeof > Args[0].sizeof)
{
alias Largest = Largest!(Args[1 .. $]);
}
else
{
alias Largest = Args[0];
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(is(Largest!(int, short, uint) == int));
static assert(is(Largest!(short) == short));
static assert(is(Largest!(ubyte[8], ubyte[5]) == ubyte[8]));
static assert(!is(Largest!(short, 5)));
}

View File

@@ -17,6 +17,7 @@
*/
module tanya.memory.allocator;
import std.traits : hasElaborateDestructor;
import tanya.memory.lifetime;
import tanya.meta.trait;

View File

@@ -14,6 +14,7 @@
*/
module tanya.memory.lifetime;
import std.traits : isInnerClass, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor;
import tanya.memory.allocator;
import tanya.meta.metafunction;
import tanya.meta.trait;
@@ -60,7 +61,7 @@ package(tanya) void destroyAllImpl(R, E)(R p)
* Postcondition: $(D_PARAM memory) and the result point to the same memory.
*/
T emplace(T, U, Args...)(void[] memory, U outer, auto ref Args args)
if (!isAbstractClass!T && isInnerClass!T && is(typeof(T.outer) == U))
if (is(T == class) && !isAbstractClass!T && isInnerClass!T && is(typeof(T.outer) == U))
in
{
assert(memory.length >= stateSize!T);

View File

@@ -20,10 +20,10 @@
*/
module tanya.algorithm.iteration;
import std.traits : Unqual;
import std.typecons;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
private struct SingletonByValue(E)

View File

@@ -14,10 +14,10 @@
*/
module tanya.algorithm.mutation;
import std.traits : Unqual, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor;
static import tanya.memory.lifetime;
static import tanya.memory.op;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
/**

View File

@@ -18,11 +18,11 @@ import core.checkedint;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.algorithm.mutation : bringToFront;
import std.traits : PointerTarget, Unqual, hasElaborateDestructor;
import tanya.algorithm.mutation;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
/**

View File

@@ -14,11 +14,11 @@
*/
module tanya.container.entry;
import std.traits : Unqual, hasElaborateDestructor;
import tanya.container.array;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
package struct SEntry(T)
{

View File

@@ -15,6 +15,7 @@
module tanya.container.hashtable;
import std.algorithm.iteration;
import std.traits : CopyConstness, Unqual, ifTestable;
import tanya.algorithm.mutation;
import tanya.container.array;
import tanya.container.entry;
@@ -22,7 +23,6 @@ import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.primitive;
/**

View File

@@ -17,11 +17,11 @@ module tanya.container.list;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.traits : Unqual;
import tanya.container.entry;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array;
import tanya.range.primitive;

View File

@@ -15,13 +15,13 @@
*/
module tanya.container.set;
import std.traits : CopyConstness, Unqual, ifTestable;
import tanya.container.array;
import tanya.container.entry;
import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.primitive;
/**

View File

@@ -28,12 +28,12 @@ module tanya.container.string;
import std.algorithm.comparison;
import std.algorithm.mutation : bringToFront;
import std.traits : CopyConstness, Unqual;
import tanya.algorithm.mutation;
import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array;
import tanya.range.primitive;

View File

@@ -14,11 +14,10 @@
*/
module tanya.conv;
import std.traits : Unsigned, isNumeric;
import std.traits : Unsigned, isNumeric, Largest, Unqual, EnumMembers;
import tanya.container.string;
import tanya.memory.allocator;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
/**

View File

@@ -49,12 +49,12 @@ module tanya.format;
import std.algorithm.comparison;
import std.ascii;
import std.traits : Unqual;
import tanya.container.string;
import tanya.math;
static import tanya.memory.op;
import tanya.meta.metafunction;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
// Returns the last part of buffer with converted number.

View File

@@ -22,8 +22,8 @@
module tanya.math;
import std.math;
import std.traits : Unqual;
import tanya.meta.trait;
import tanya.meta.transform;
/// Floating-point number precisions according to IEEE-754.
enum IEEEPrecision : ubyte

View File

@@ -14,10 +14,10 @@
*/
module tanya.net.iface;
import std.traits : Unqual;
import tanya.algorithm.mutation;
import tanya.container.string;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
version (Windows)

View File

@@ -14,8 +14,8 @@
*/
module tanya.net.inet;
import std.traits : Unqual;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
/**

View File

@@ -18,6 +18,7 @@ import std.algorithm.comparison;
import std.ascii;
import std.sumtype;
import std.typecons;
import std.traits : Unqual;
import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
import tanya.container.string;
@@ -25,7 +26,6 @@ import tanya.conv;
import tanya.format;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.net.iface;
import tanya.net.inet;
import tanya.range;

View File

@@ -15,9 +15,9 @@
module tanya.range.primitive;
import std.algorithm.comparison;
import std.traits : FunctionAttribute, hasElaborateCopyConstructor, functionAttributes;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array;
/**

View File

@@ -90,8 +90,8 @@ struct WithLvalueElements
*/
mixin template InputRangeStub(E = int)
{
import std.traits : hasUDA, getUDAs;
import tanya.meta.metafunction : Alias;
import tanya.meta.trait : evalUDA, getUDAs, hasUDA;
/*
* Aliases for the attribute lookups to access them faster
@@ -113,7 +113,7 @@ mixin template InputRangeStub(E = int)
}
else static if (Length.length != 0)
{
private enum size_t count = evalUDA!(Length[0]).length;
private enum size_t count = Length[0]().length;
static assert (!infinite,
"Range cannot have length and be infinite at the same time");
@@ -372,7 +372,7 @@ struct Hashable
*/
mixin template StructStub()
{
import tanya.meta.trait : evalUDA, getUDAs, hasUDA;
import std.traits : hasUDA, getUDAs;
static if (hasUDA!(typeof(this), NonCopyable))
{
@@ -384,7 +384,7 @@ mixin template StructStub()
{
size_t toHash() const @nogc nothrow pure @safe
{
return evalUDA!(Hashable[0]).hash;
return Hashable[0]().hash;
}
}

View File

@@ -89,84 +89,3 @@ import tanya.meta.trait;
static assert(is(FunctionTypeOf!S2 == function));
static assert(is(FunctionTypeOf!s2 == function));
}
@nogc nothrow pure @safe 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);
}
// Produces a tuple for an enum with only one member
@nogc nothrow pure @safe unittest
{
enum E : int
{
one = 0,
}
static assert(EnumMembers!E == AliasSeq!0);
}
@nogc nothrow pure @safe unittest
{
class RefCountedStore(T)
{
}
static assert(!isInnerClass!(RefCountedStore!int));
}
@nogc nothrow pure @safe unittest
{
static struct DisabledOpEquals
{
@disable bool opEquals(typeof(this)) @nogc nothrow pure @safe;
int opCmp(typeof(this)) @nogc nothrow pure @safe
{
return 0;
}
}
static assert(!isEqualityComparable!DisabledOpEquals);
static assert(isOrderingComparable!DisabledOpEquals);
static struct OpEquals
{
bool opEquals(typeof(this)) @nogc nothrow pure @safe
{
return true;
}
}
static assert(isEqualityComparable!OpEquals);
static assert(!isOrderingComparable!OpEquals);
}