mirror of
https://github.com/dlang/phobos.git
synced 2025-05-02 16:10:45 +03:00
146 lines
3.4 KiB
D
146 lines
3.4 KiB
D
module std.experimental.allocator.common;
|
|
import std.traits;
|
|
|
|
/*
|
|
Ternary by Timon Gehr and Andrei Alexandrescu.
|
|
*/
|
|
struct Ternary
|
|
{
|
|
private ubyte value = 6;
|
|
private static Ternary make(ubyte b)
|
|
{
|
|
Ternary r = void;
|
|
r.value = b;
|
|
return r;
|
|
}
|
|
|
|
enum no = make(0), yes = make(2), unknown = make(6);
|
|
|
|
this(bool b) { value = b << 1; }
|
|
|
|
void opAssign(bool b) { value = b << 1; }
|
|
|
|
Ternary opUnary(string s)() if (s == "~")
|
|
{
|
|
return make(386 >> value & 6);
|
|
}
|
|
|
|
Ternary opBinary(string s)(Ternary rhs) if (s == "|")
|
|
{
|
|
return make(25512 >> value + rhs.value & 6);
|
|
}
|
|
|
|
Ternary opBinary(string s)(Ternary rhs) if (s == "&")
|
|
{
|
|
return make(26144 >> value + rhs.value & 6);
|
|
}
|
|
|
|
Ternary opBinary(string s)(Ternary rhs) if (s == "^")
|
|
{
|
|
return make(26504 >> value + rhs.value & 6);
|
|
}
|
|
}
|
|
|
|
unittest
|
|
{
|
|
alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
|
|
auto truthTableAnd =
|
|
[
|
|
t, t, t,
|
|
t, u, u,
|
|
t, f, f,
|
|
u, t, u,
|
|
u, u, u,
|
|
u, f, f,
|
|
f, t, f,
|
|
f, u, f,
|
|
f, f, f,
|
|
];
|
|
|
|
auto truthTableOr =
|
|
[
|
|
t, t, t,
|
|
t, u, t,
|
|
t, f, t,
|
|
u, t, t,
|
|
u, u, u,
|
|
u, f, u,
|
|
f, t, t,
|
|
f, u, u,
|
|
f, f, f,
|
|
];
|
|
|
|
auto truthTableXor =
|
|
[
|
|
t, t, f,
|
|
t, u, u,
|
|
t, f, t,
|
|
u, t, u,
|
|
u, u, u,
|
|
u, f, u,
|
|
f, t, t,
|
|
f, u, u,
|
|
f, f, f,
|
|
];
|
|
|
|
for (auto i = 0; i != truthTableAnd.length; i += 3)
|
|
{
|
|
assert((truthTableAnd[i] & truthTableAnd[i + 1])
|
|
== truthTableAnd[i + 2]);
|
|
assert((truthTableOr[i] | truthTableOr[i + 1])
|
|
== truthTableOr[i + 2]);
|
|
assert((truthTableXor[i] ^ truthTableXor[i + 1])
|
|
== truthTableXor[i + 2]);
|
|
}
|
|
|
|
Ternary a;
|
|
assert(a == Ternary.unknown);
|
|
static assert(!is(typeof({ if (a) {} })));
|
|
assert(!is(typeof({ auto b = Ternary(3); })));
|
|
a = true;
|
|
assert(a == Ternary.yes);
|
|
a = false;
|
|
assert(a == Ternary.no);
|
|
a = Ternary.unknown;
|
|
assert(a == Ternary.unknown);
|
|
Ternary b;
|
|
b = a;
|
|
assert(b == a);
|
|
assert(~Ternary.yes == Ternary.no);
|
|
assert(~Ternary.no == Ternary.yes);
|
|
assert(~Ternary.unknown == Ternary.unknown);
|
|
}
|
|
|
|
/**
|
|
Returns the size in bytes of the state that needs to be allocated to hold an
|
|
object of type $(D T). $(D stateSize!T) is zero for $(D struct)s that are not
|
|
nested and have no nonstatic member variables.
|
|
*/
|
|
template stateSize(T)
|
|
{
|
|
static if (is(T == class) || is(T == interface))
|
|
enum stateSize = __traits(classInstanceSize, T);
|
|
else static if (is(T == struct) || is(T == union))
|
|
enum stateSize = FieldTypeTuple!T.length || isNested!T ? T.sizeof : 0;
|
|
else static if (is(T == void))
|
|
enum size_t stateSize = 0;
|
|
else
|
|
enum stateSize = T.sizeof;
|
|
}
|
|
|
|
unittest
|
|
{
|
|
static assert(stateSize!void == 0);
|
|
struct A {}
|
|
static assert(stateSize!A == 0);
|
|
struct B { int x; }
|
|
static assert(stateSize!B == 4);
|
|
interface I1 {}
|
|
//static assert(stateSize!I1 == 2 * size_t.sizeof);
|
|
class C1 {}
|
|
static assert(stateSize!C1 == 3 * size_t.sizeof);
|
|
class C2 { char c; }
|
|
static assert(stateSize!C2 == 4 * size_t.sizeof);
|
|
static class C3 { char c; }
|
|
static assert(stateSize!C3 == 2 * size_t.sizeof + char.sizeof);
|
|
}
|