How to separarte lvalue parameter from rvalue?
realhet
real_het at hotmail.com
Mon Sep 14 10:51:38 UTC 2026
Hi! I try to make the easiest syntax for manipulating bits.
Examples:
```d
value.asBits[3..5] = 2;
writeln(value.asBits[3..5].as!uint);
```
For the entry point I chose from 2 implementations:
```d
auto asBits(D)(ref D data)
=> BitsRefSlice!D(&data, 0, D.sizeof*8);
auto asBits(D)(D data)
=> BitsValSlice!D(data, 0, D.sizeof*8);
```
But this is wrong. If I give it immutable data, it will chose
BitRefSlice. And BitRefSlice stores a pointer to data inside.
How can I detect it properly?
Here's the whole thing:
```d
struct BitsRefSlice(D)
{
private { D* pdata; size_t st, en; }
size_t opDollar(size_t pos)()
=> D.sizeof*8 - st;
auto opIndex()(size_t i)
=> BitsRefIndex!D(pdata, this.st+i).get;
auto opIndexAssign()(bool v, size_t i)
=> BitsRefIndex!D(pdata, this.st+i).set(v);
auto opSlice(size_t st, size_t en)
=> BitsRefSlice!D(pdata, this.st+st, this.st+en);
auto opSlice()
=> this[0..$];
auto as(T)()
=> BitsValSlice!D(*pdata, st, en).as!T;
auto as(T)(in T val)
{
const msk0 = ((1UL<<(en-st))-1),
msk = msk0<<st;
(*pdata) = (cast(D)((*pdata)&~msk | ((val&msk0)<<st)));
return val;
}
auto get() => BitsValSlice!D(*pdata, st, en).get;
auto access() => get;
auto access(T)(in T val) => as = val;
alias this = access;
} struct BitsValSlice(D)
{
private { D data; size_t st, en; }
size_t opDollar(size_t pos)()
=> D.sizeof*8 - st;
auto opIndex()(size_t i)
=> BitsValIndex!D(data, this.st+i).get;
auto opSlice(size_t st, size_t en)
=> BitsValSlice!D(data, this.st+st, this.st+en);
auto opSlice()
=> this[0..$];
auto as(T)()
{
auto res = (cast(T)((data>>st) & ((1UL<<(en-st))-1)));
static if(isIntegral!T && isSigned!T)
{
const sh = T.sizeof*8 - (en-st);
res = (cast(T)((cast(T)(res<<sh))>>sh)); /+sign extend+/
}
return res;
}
static if(D.sizeof<=4) { alias DefaultType = uint; }
else { alias DefaultType = ulong; }
auto get() => as!DefaultType;
alias this = get;
}
struct BitsRefIndex(D)
{
private { D* pdata; size_t idx; }
bool get() => BitsValIndex!D(*pdata, idx).get;
bool set(bool v)
{
*pdata = (cast(D)((*pdata)&~(1UL<<idx)|((cast(D)(v))<<idx)));
return v;
}
bool access() => get;
bool access(bool v) => set(v);
alias this = access;
} struct BitsValIndex(D)
{
private { D data; size_t idx; }
bool get() => !!((data>>idx)&1);
alias this = get;
}
auto asBits(D)(ref D data)
=> BitsRefSlice!D(&data, 0, D.sizeof*8);
auto asBits(D)(D data)
=> BitsValSlice!D(data, 0, D.sizeof*8);
bool test_bits()
{
ubyte b = 0x55; enforce(b.asBits[4..8]==5);
b.asBits[4..8] = -1; enforce(b.asBits[]==0xF5);
enforce(b.asBits[].as!int==-11);
enforce((0x696).asBits[4..$].as!ubyte==0x69);
return true;
}
```
More information about the Digitalmars-d-learn
mailing list