www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Casting to union type?

reply "cc" <cc nevernet.com> writes:
Is it possible to allow implicit casting from a base type to a
union type?  For example, considering the following basic vector
union:

union vec2 {
	struct {
		float x = 0.0f;
		float y = 0.0f;
	}
	float[2] v;
	enum length = v.length;

	ref auto opIndex(size_t idx) {
		assert(idx >= 0 && idx < length, "Bounds error on index");
		return v[idx];
	}
	auto opAssign(float[] f) {
		assert(f.length == length, "Bounds error on assignment");
		v[0..length] = f[0..length];
		return this;
	}
}

vec2 a = vec2(1.0, 2.0); // fine
vec2 b;
b = [3.0, 4.0]; //fine
vec2 c = [5.0, 6.0]; // cannot cast float[] to vec2


Overloading opCast() seems to be only for "outbound" casting, and
unions can't have this() constructors like structs.  Is there any
way to accomplish this?
Aug 25 2014
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, 26 August 2014 at 02:33:25 UTC, cc wrote:
 Is it possible to allow implicit casting from a base type to a
 union type?
All implict conversions are done using alias this: http://dlang.org/class.html#AliasThis - Jonathan M Davis
Aug 25 2014
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 26 August 2014 at 02:33:25 UTC, cc wrote:
 vec2 a = vec2(1.0, 2.0); // fine
 vec2 b;
 b = [3.0, 4.0]; //fine
 vec2 c = [5.0, 6.0]; // cannot cast float[] to vec2
There is currently no implicit for aggregates except using `alias this`. But in your example, it's a construction, not an assignment, so you need to write an appropriate constructor `this(float[])` analogous to `opAssign(float[])`.
Aug 26 2014
parent "cc" <cc nevernet.com> writes:
Ahh, thanks.  Looks like encapsulating the union in a struct with 
alias this gets the job done, and removes the need for overloads. 
  Neat.

struct vec2 {
	union {
		struct {
			float x = 0.0f;
			float y = 0.0f;
		}
		float[2] v;
	}

	this(float x, float y) {
		this.x = x;
		this.y = y;
	}
	this(float[v.length] f) {
		v[0..length] = f[0..length];
	}
	alias v this;
}
Aug 26 2014