Jump to page: 1 2
Thread overview
AA and struct with const member
Dec 27, 2021
frame
Dec 28, 2021
Era Scarecrow
Dec 28, 2021
Tejas
Dec 28, 2021
frame
Dec 28, 2021
tsbockman
Dec 28, 2021
frame
Dec 29, 2021
Stanislav Blinov
Dec 29, 2021
frame
Dec 29, 2021
Stanislav Blinov
Dec 29, 2021
Era Scarecrow
Dec 28, 2021
frame
Dec 28, 2021
Era Scarecrow
Dec 28, 2021
frame
December 27, 2021

I feel stupid right now: One cannot assign a struct that contains const member to AA?

Error: cannot modify struct instance ... of type ... because it contains const or immutable members

This is considered a modification?

struct S
{
  const(int) a;
}

S[string] test;
test["a"] = S(1);

Whats the workaround for that?

December 28, 2021

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:

>

I feel stupid right now: One cannot assign a struct that contains const member to AA?

Error: cannot modify struct instance ... of type ... because it contains const or immutable members

This is considered a modification?

struct S
{
  const(int) a;
}

S[string] test;
test["a"] = S(1);

Whats the workaround for that?

const/immutable members are to be set/assigned instantiation. Most likely the problem is a bug and sounds like

a) the struct doesn't exist in the AA, so it creates it (with a default)
b) It tries to copy but contains a const and thus fails

Passing a pointer will do you no good, since structs are likely to be on the stack.

So let's try opAssign.

  auto ref opAssign(S s) {
	this=s;
	return this;
  }

So we get

'cannot modify struct instance `this` of type `S` because it contains `const` or `immutable` members'.

Alright let's look at the members we can work with.
https://dlang.org/spec/hash-map.html

I don't see an 'add' but i do see a 'require' which will add something in. So we try that.

test.require("a", S(1));

Now we get:
Error: cannot modify struct instance `*p` of type `S` because it contains `const` or `immutable` members
test.d(??): Error: template instance `object.require!(string, S)` error instantiating

Hmmm it really doesn't like it. Finally we can fake it. Let's make a mirror struct without the const, for the purposes of adding it.

struct S
{
  const(int) a;
}

struct S2
{
  int a;
}

S[string] test;
cast(S2[string])test = S2(1);
Error: `cast(S2[string])test` is not an lvalue and cannot be modified

Well that's not going to work. Let's make it a pointer and allocate it instead.

S*[string] test;
test["a"] = new S(1);

Success!

So i summarize, either work with a pointer, or drop the const...

December 28, 2021

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:

>

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:

>

[...]

const/immutable members are to be set/assigned instantiation. Most likely the problem is a bug and sounds like

[...]

The workaround is okay, but I think we should file a bug report for this.
This is very stupid undesirable behaviour

December 28, 2021

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:

>

Success!

So i summarize, either work with a pointer, or drop the const...

Of course casting the const away was the first thing I did but I think this is not very clean :D

December 28, 2021

On Tuesday, 28 December 2021 at 06:38:03 UTC, Tejas wrote:

>

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:

>

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:

>

[...]

const/immutable members are to be set/assigned instantiation. Most likely the problem is a bug and sounds like

[...]

The workaround is okay, but I think we should file a bug report for this.
This is very stupid undesirable behaviour

I agree. I'll just wait if somebody can explain why this isn't a bug or wanted behaviour or a known issue.

December 28, 2021

On Tuesday, 28 December 2021 at 07:54:56 UTC, frame wrote:

>

On Tuesday, 28 December 2021 at 06:38:03 UTC, Tejas wrote:

>

The workaround is okay, but I think we should file a bug report for this.
This is very stupid undesirable behaviour

I agree. I'll just wait if somebody can explain why this isn't a bug or wanted behaviour or a known issue.

The spec says:

2. If the assigned value type is equivalent with the AA element type:

    1. If the indexing key does not yet exist in AA, a new AA entry will be allocated, and it will be initialized with the assigned value.
    2. If the indexing key already exists in the AA, the setting runs normal assignment.

Thus, when the value type is constructable but not assignable:

struct S
{
  const(int) a;
}

void test(S[string] aa, string key, int value)
{
  // Should be a compile-time error, because it might reassign:
  test[key] = S(value);

  // Should be accepted, because they can be proven at compile time to never reassign:
  test.require("a", S(value));
  test.update("a", () => S(value), (ref const(S)) => { });
}

require and update can be fixed rather easily in object.d; I have submitted issue 22633 with sample code.

December 28, 2021

On Tuesday, 28 December 2021 at 07:51:04 UTC, frame wrote:

>

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:

>

Success!

So i summarize, either work with a pointer, or drop the const...

Of course casting the const away was the first thing I did but I think this is not very clean :D

Well the next step up would be if the key does exist, you could then memcpy the result... which can have issues with non-native basic types.

Probably better to make data private vs making it const. I tend to use const far more as input arguments to help denote it won't change references and less for elements in a struct. That or make it a class? I'm not sure.

December 28, 2021

On Tuesday, 28 December 2021 at 14:48:24 UTC, Era Scarecrow wrote:

>

Probably better to make data private vs making it const. I tend to use const far more as input arguments to help denote it won't change references and less for elements in a struct. That or make it a class? I'm not sure.

It's a matter of consistency - if a function returns something in const one should be able to store it without any type modification.

December 28, 2021

On Tuesday, 28 December 2021 at 10:02:13 UTC, tsbockman wrote:

>

// Should be a compile-time error, because it might reassign:
test[key] = S(value);

This might be a typo in your example but why should it be a compile-time error, it cannot know if the key already exists in compile time on a variable. First time initialization should always work anyway.

>

require and update can be fixed rather easily in object.d; I have submitted issue 22633 with sample code.

Perfect. Thank you.

December 29, 2021

On Tuesday, 28 December 2021 at 22:46:16 UTC, frame wrote:

>

On Tuesday, 28 December 2021 at 10:02:13 UTC, tsbockman wrote:

>

// Should be a compile-time error, because it might reassign:
test[key] = S(value);

This might be a typo in your example but why should it be a compile-time error, it cannot know if the key already exists in compile time on a variable. First time initialization should always work anyway.

Because opIndexAssign cannot distinguish at compile time between initialization and assignment:

Stuff[Key] aa;
aa[key] = Stuff(args); // ostensibly, initialization
aa[key] = otherStuff;  // assignment to existing value

Same syntax, different behavior. This can only be caught at runtime. require and update though should be able to pull this off, and that they don't is a bug.

« First   ‹ Prev
1 2