Thread overview
Casting to union type?
Aug 26, 2014
cc
Aug 26, 2014
Jonathan M Davis
Aug 26, 2014
Marc Schütz
Aug 26, 2014
cc
August 26, 2014
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?
August 26, 2014
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
August 26, 2014
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[])`.
August 26, 2014
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;
}