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?

```d
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.

Reply via email to