Thread overview
Is there a more elegant way to do this?
Mar 12, 2017
bauss
Mar 12, 2017
bauss
Mar 12, 2017
Nicholas Wilson
March 12, 2017
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
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
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;
}