Re: Default struct constructors if a struct member is a union

2024-07-06 Thread cc via Digitalmars-d-learn

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.



Re: Default struct constructors if a struct member is a union

2024-07-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:


My usecase scenario doesn't really allow constructors for the 
struct, since it's a binding to an external library via C API.


BTW, this is not true. A constructor does not change the struct 
layout or anything about it from the C side. You can safely add 
the struct constructor (or any other struct member functions) and 
the struct itself should be C compatible.


-Steve


Re: Default struct constructors if a struct member is a union

2024-07-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:

```d
union U {
int i32;
long i64;
float f32;
double f64;
}

struct S {
TypeEnum type;
U data;
}

S foo0 = S(TypeEnum.Integer32, S(20));  //Ugly, but works
S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot 
implicitly convert expression

//ditto for the rest of the members
```

My question is can I initialize structs like these in one line 
without relying on a second line? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding 
to an external library via C API.


Have you tried named parameter construction?

```d
S foo2 = S(TypeEnum.Float32, U(f32: 20.0));
```

-Steve



Re: Default struct constructors if a struct member is a union

2024-06-30 Thread Basile B. via Digitalmars-d-learn

On Sunday, 30 June 2024 at 11:23:45 UTC, Nick Treleaven wrote:

On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:

S foo0 = S(TypeEnum.Integer32, S(20));  //Ugly, but works
S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot


Did you mean `U(20)`? The 20 applies to the first field of the 
union, i32. `U(20L)` also works and (I think) it does the same 
because of VRP.


My question is can I initialize structs like these in one line 
without relying on a second line? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding 
to an external library via C API.


You can use a field initializer:
```d
enum TypeEnum { Integer32, Integer64 }

union U {
int i32;
long i64;
float f32;
double f64;
}

struct S {
TypeEnum type;
U data;
}

S foo0 = S(TypeEnum.Integer32, U(20)); // init i32
S foo1 = S(TypeEnum.Integer64, U(f32: 0.5F));

// struct initializer syntax
S foo2 = {TypeEnum.Integer32, {20}};
S foo3 = {TypeEnum.Integer64, {f32: 0.5F}}; // init f32

void main()
{
assert(foo0.data.i32 == 20);
assert(foo3.data.f32 == 0.5F);
}
```


That's another solution, that being said, the real problem OP 
encountered is the classic one of "implict construction", which 
is not a D thing.


Re: Default struct constructors if a struct member is a union

2024-06-30 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:

S foo0 = S(TypeEnum.Integer32, S(20));  //Ugly, but works
S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot


Did you mean `U(20)`? The 20 applies to the first field of the 
union, i32. `U(20L)` also works and (I think) it does the same 
because of VRP.


My question is can I initialize structs like these in one line 
without relying on a second line? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding 
to an external library via C API.


You can use a field initializer:
```d
enum TypeEnum { Integer32, Integer64 }

union U {
int i32;
long i64;
float f32;
double f64;
}

struct S {
TypeEnum type;
U data;
}

S foo0 = S(TypeEnum.Integer32, U(20)); // init i32
S foo1 = S(TypeEnum.Integer64, U(f32: 0.5F));

// struct initializer syntax
S foo2 = {TypeEnum.Integer32, {20}};
S foo3 = {TypeEnum.Integer64, {f32: 0.5F}}; // init f32

void main()
{
assert(foo0.data.i32 == 20);
assert(foo3.data.f32 == 0.5F);
}
```


Re: Default struct constructors if a struct member is a union

2024-06-29 Thread Basile B. via Digitalmars-d-learn

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? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding 
to an external library via C API.


Apprently that works with an anonymous union:

```d
enum TypeEnum {
Integer32,
Integer64,
Float32,
Float64,
}

struct S {

TypeEnum type;

union {
int i32;
long i64;
float f32;
double f64;
}
}

S foo0 = S(TypeEnum.Integer32, 20);
S foo1 = S(TypeEnum.Integer64, 20L);
```



Default struct constructors if a struct member is a union

2024-06-29 Thread solidstate1991 via Digitalmars-d-learn

```d
union U {
int i32;
long i64;
float f32;
double f64;
}

struct S {
TypeEnum type;
U data;
}

S foo0 = S(TypeEnum.Integer32, S(20));  //Ugly, but works
S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot 
implicitly convert expression

//ditto for the rest of the members
```

My question is can I initialize structs like these in one line 
without relying on a second line? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding to 
an external library via C API.