| |
|
cc ![cc's Gravatar profile Gravatar of cc](//www.gravatar.com/avatar/ef871764bb96514086e6e6289ac3f5f3?d=identicon&s=80)
Posted in reply to solidstate1991
| On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:
> My question is can I initialize structs like these in one line without relying on a second line?
template ValueOfUDAType(alias T, alias UDA) {
static foreach (uidx, U; __traits(getAttributes, T)) static if (is(typeof(U) == UDA)) enum UDA ValueOfUDAType = U;
}
struct S {
enum TypeEnum {
Integer32,
Integer64,
Float32,
Float64,
}
union U {
@(TypeEnum.Integer32) int i32;
@(TypeEnum.Integer64) long i64;
@(TypeEnum.Float32) float f32;
@(TypeEnum.Float64) double f64;
}
TypeEnum type;
U data;
this(T)(T t) { opAssign(t); }
void opAssign(S rhs) {
static foreach (idx, field; S.tupleof) {
this.tupleof[idx] = rhs.tupleof[idx];
}
}
void opAssign(T)(T t) {
static foreach (idx, field; data.tupleof) static if (is(T == typeof(field))) {
type = ValueOfUDAType!(field, TypeEnum);
data.tupleof[idx] = t;
static assert(!is(typeof(FOUND)), "Assigning type "~fullyQualifiedName!T~" matches multiple candidates "~fullyQualifiedName!U);
enum bool FOUND = true;
}
static assert(is(typeof(FOUND)), "Cannot assign type "~fullyQualifiedName!T~" to "~fullyQualifiedName!U);
}
T get(T)() {
static foreach (idx, field; data.tupleof) static if (is(T == typeof(field))) {
enforce(type == ValueOfUDAType!(field, TypeEnum), "Type mismatch requesting "~fullyQualifiedName!T);
return data.tupleof[idx];
}
}
bool is_a(T)() {
static foreach (idx, field; data.tupleof) static if (is(T == typeof(field))) {
return (type == ValueOfUDAType!(field, TypeEnum));
}
}
}
S s = 3.14f;
assert(s.type == S.TypeEnum.Float32);
s = 9.17;
assert(s.type == S.TypeEnum.Float64);
if (s.is_a!double) {
writeln(s.get!double);
}
try {
int n = s.get!int;
} catch (Exception e) {
writeln("Not an int");
}
s = 20;
assert(s.type == S.TypeEnum.Integer32);
s = 40L;
assert(s.type == S.TypeEnum.Integer64);
Or just use SumType.
|