www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there a more elegant way to do this?

reply bauss <jj_1337 live.dk> writes:
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?
Mar 11 2017
next sibling parent bauss <jj_1337 live.dk> writes:
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));
Mar 11 2017
prev sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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; }
Mar 11 2017