Has anybody cooked up some generic functions that extend core.bitop
bitmanipulations to work on any value type?
Something like
bool getBit(T)(in T a, int bitnum); // bt
T setBit(T)(in T a, int bitnum); // bts
auto ref setBitInPlace(T)(ref T a, int bitnum);
I know this is relatively easy to implement so that's why I'm curious to why its not already Phobos.
Update:
Here's my first try at this:
bool getBit(T, I)(in T a, I bitnum) @safe pure nothrow if (isIntegral!T &&
isIntegral!I) {
return a & (((cast(I)1) << bitnum)) ? true : false;
}
bool getBit(T, I)(in T a, I bitnum) @trusted pure nothrow if ((!(isIntegral!T)) &&
isIntegral!I) {
enum nBits = 8*T.sizeof;
static if (nBits == 8) alias I = ubyte;
else static if (nBits == 16) alias I = ushort;
else static if (nBits == 32) alias I = uint;
else static if (nBits == 64) alias I = ulong;
return (*(cast(I*)&a)).getBit(bitnum); // reuse integer variant
}
alias bt = getBit;
My idea is to make getBit
work on all types that have value semantics. That's why I need the cast (I think). Is there a traits to check if a type has value semantics or not?
Also is there a trait to check if a type supports a specific operation such as bitwise and &
? I could always use __traits(compiles, ...)
but standardization is good.
To make it even better I guess I need an explicit overload for T's that support bit manipulations in order to make this variant @safe right? In my generic solution above I need the cast
and that's @unsafe.
Is there a traits to check if a type has value semantics or not?
There is no trait for value types, at least not in the documentation However, I have checked for value types before using the "is expression":
import std.stdio;
struct Foo {}
auto fn(T)(T type)
{
static if (is(T == struct)) {
writeln(T.stringof ~ " is a value type");
} else if (is(T == class)) {
writeln(T.stringof ~ " is a reference type");
} else {
writeln(T.stringof ~ " is something else");
}
}
void main()
{
Foo f;
fn(f);
fn(new Object());
fn(1);
}
Also is there a trait to check if a type supports a specific operation such as bitwise and &?
Other than the trait for compiles, this can also be achieved with an is expression. This is similar to how it is currently done for ranges, for example:
import std.stdio;
struct Foo {
auto opBinary(string op)(Foo rhs)
if (op == "&")
{
return rhs.init; // dummy implementation
}
};
template canUseBitOps(T)
{
enum bool canUseBitOps = is(typeof(
(inout int = 0)
{
T t1 = T.init;
T t2 = T.init;
auto r = t1 & t2;
}));
}
void main()
{
assert(canUseBitOps!int);
assert(!canUseBitOps!string);
assert(canUseBitOps!Foo);
}