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