| Thread overview | |||||
|---|---|---|---|---|---|
|
March 12, 2017 Is there a more elegant way to do this? | ||||
|---|---|---|---|---|
| ||||
I was wondering if there's a more elegant way to do something like this?
template BitSize(T) {
enum BitSize = T.sizeof * 8;
}
struct Data(ParentType,ChildType) {
@property {
ChildType low() { return cast(ChildType)value; }
void low(ChildType lowValue) {
value = ((high << (BitSize!ParentType / 2)) | lowValue);
}
ChildType high() { return cast(ChildType)(value >> (BitSize!ParentType / 2)); }
void high(ChildType highValue) {
value = ((highValue << 16 | low));
}
}
ParentType value;
alias value this;
}
Example usage:
void main() {
Data!(uint,ushort) data;
data = 14065735;
writefln("low: %s high: %s", data.low, data.high);
data.low = 41031 ;
data.high = 214;
writefln("value: %s", data.value);
}
Basically to explain what it is: You give it a parent-type and a corresponding child-type.
Ex. if the parent-type is uint, the child-type would be ushort.
if the parent-type is long, the child-type would be int.
etc.
What it allows you to is to either manipulate the data as the parent-type or as two values of the child type.
I was just wondering if there's a more elegant or performant way to do this, perhaps something in Phobos exist already?
| ||||
March 12, 2017 Re: Is there a more elegant way to do this? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bauss | On Sunday, 12 March 2017 at 05:13:41 UTC, bauss wrote:
> I was wondering if there's a more elegant way to do something like this?
>
> [...]
I saw one improvement to it which would be BitSize!ChildType instead of taking parent type's bit size divided by two.
Also
value = ((highValue << 16 | low));
Is supposed to be
value = ((highValue << BitSize!ChildType | low));
| |||
March 12, 2017 Re: Is there a more elegant way to do this? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bauss | On Sunday, 12 March 2017 at 05:13:41 UTC, bauss wrote:
> I was wondering if there's a more elegant way to do something like this?
>
> template BitSize(T) {
> enum BitSize = T.sizeof * 8;
> }
>
> struct Data(ParentType,ChildType) {
> @property {
> ChildType low() { return cast(ChildType)value; }
> void low(ChildType lowValue) {
> value = ((high << (BitSize!ParentType / 2)) | lowValue);
> }
>
> ChildType high() { return cast(ChildType)(value >> (BitSize!ParentType / 2)); }
> void high(ChildType highValue) {
> value = ((highValue << 16 | low));
> }
> }
>
> ParentType value;
>
> alias value this;
> }
>
> Example usage:
> void main() {
> Data!(uint,ushort) data;
> data = 14065735;
>
> writefln("low: %s high: %s", data.low, data.high);
>
> data.low = 41031 ;
> data.high = 214;
>
> writefln("value: %s", data.value);
> }
>
> Basically to explain what it is: You give it a parent-type and a corresponding child-type.
>
> Ex. if the parent-type is uint, the child-type would be ushort.
> if the parent-type is long, the child-type would be int.
> etc.
>
> What it allows you to is to either manipulate the data as the parent-type or as two values of the child type.
>
> I was just wondering if there's a more elegant or performant way to do this, perhaps something in Phobos exist already?
template HalfSize(T)
{
static if (T==long)
alias HalfSize == int;
// repeat for all combos
}
struct Data(T)
{
union
{
T value;
struct
{
version(LittleEndian)
{
HalfSize!T low;
HalfSize!T high;
}
version(BigEndian)
{
HalfSize!T low;
HalfSize!T high;
}
}
}
alias value this;
}
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply