View mode: basic / threaded / horizontal-split · Log in · Help
September 08, 2012
const attribute makes whole element const?
Why fail this code?
without "const" on "Name" it works fine.

http://dpaste.dzfl.pl/9fa0986a
September 08, 2012
Re: const attribute makes whole element const?
On 09/09/2012 01:16 AM, Namespace wrote:
> Why fail this code?
> without "const" on "Name" it works fine.
>
> http://dpaste.dzfl.pl/9fa0986a

const fields cannot be written to. This includes the case when the
entire struct is written to at once.
September 09, 2012
Re: const attribute makes whole element const?
On Saturday, 8 September 2012 at 23:18:14 UTC, Timon Gehr wrote:
> On 09/09/2012 01:16 AM, Namespace wrote:
>> Why fail this code?
>> without "const" on "Name" it works fine.
>>
>> http://dpaste.dzfl.pl/9fa0986a
>
> const fields cannot be written to. This includes the case when 
> the
> entire struct is written to at once.

That doesn't make sense to me either. Why would the entire 
"tests[4]" be immutable? If I were to define CC and opAssign, 
then why is there still a problem?

Further more, changing from Associative Array to raw array solves 
the problem.

This is a strange behavior for AAs.

void main() {
    struct Test {
        const string Name;

        this(string name) {
            this.Name = name;
        }

        this(Test other)
        {}

        void opAssign(Test other)
        {}
    }

    Test[string] tests;
    Test t2 = Test("FooBar");
    Test t3;
    t3 = t2;
    auto t4 = tests[4];
    tests[4] = t4;
}
September 09, 2012
Re: const attribute makes whole element const?
On Saturday, 8 September 2012 at 23:18:14 UTC, Timon Gehr wrote:
> On 09/09/2012 01:16 AM, Namespace wrote:
>> Why fail this code?
>> without "const" on "Name" it works fine.
>>
>> http://dpaste.dzfl.pl/9fa0986a
>
> const fields cannot be written to. This includes the case when 
> the
> entire struct is written to at once.

But i assign the const attribute in the ctor. So this behaviour 
doesn't make any sense...
September 09, 2012
Re: const attribute makes whole element const?
On 09/09/2012 08:09 AM, Namespace wrote:
> On Saturday, 8 September 2012 at 23:18:14 UTC, Timon Gehr wrote:
>> On 09/09/2012 01:16 AM, Namespace wrote:
>>> Why fail this code?
>>> without "const" on "Name" it works fine.
>>>
>>> http://dpaste.dzfl.pl/9fa0986a
>>
>> const fields cannot be written to. This includes the case when the
>> entire struct is written to at once.
>
> But i assign the const attribute in the ctor.

The constructor is not involved in that syntax.

> So this behaviour doesn't  make any sense...

The problem is with the internal workings of the marked line below:

    struct Test {
        const string Name;
        // ...
    }

    Test[string] tests;
    // ...
    tests[4] = t4;    // <--

tests[4] is an expression that automatically creates a default Test 
object and associates that default object with key 4. Then the line 
above becomes an assignment on top of that object, which can't happen 
because of the const member.

Associative arrays must have an insert() function if it does not already 
exist:

    tests.insert(4, t4);    // does this exist?

Ali
September 09, 2012
Re: const attribute makes whole element const?
On Sunday, September 09, 2012 17:09:23 Namespace wrote:
> On Saturday, 8 September 2012 at 23:18:14 UTC, Timon Gehr wrote:
> > On 09/09/2012 01:16 AM, Namespace wrote:
> >> Why fail this code?
> >> without "const" on "Name" it works fine.
> >> 
> >> http://dpaste.dzfl.pl/9fa0986a
> > 
> > const fields cannot be written to. This includes the case when
> > the
> > entire struct is written to at once.
> 
> But i assign the const attribute in the ctor. So this behaviour
> doesn't make any sense...

const member variables can be initialized but never assigned to. They're 
either directly initialized or initialized by the constructor. After that 
(including later in the constructor), you can't change them. This also makes 
the default assignment operator illegal. You could overload it, and as long as 
it doesn't touch any of the const member variables, it would work, but the 
const member variable is stuck as it is, and anything trying to mutate is 
illegal.

Really, having const member variables is a _bad_ idea IMHO - particularly for 
structs. At least with a class, if you try and replace the object's value, you 
generally just allocate a new object and assign it to the reference. But with 
structs, which are almost always on the stack, you can't assign to it anymore 
once it has a const member variable, which causes all kinds of annoying 
problems. You're just better off if you never declare structs with const or 
immutable member variables.

- Jonathan M Davis
September 10, 2012
Re: const attribute makes whole element const?
I had never problems with that in C++.
If I have members which are const because they are assigned only 
one time and needs no other assignment, why should I declare this 
member not as const?

In the example I know exactly that I assign only one time a name 
to this struct, so why I should not declare it as const?

Other example: you have a unique birthday date. This is const you 
cannot change it like a name or a telephone number. So if you 
have a Person struct which holds any data of a single people, you 
won't declare the date as const? I would. And I had expected that 
this is normal behaviour.
September 10, 2012
Re: const attribute makes whole element const?
On Monday, September 10, 2012 02:05:08 Namespace wrote:
> I had never problems with that in C++.
> If I have members which are const because they are assigned only
> one time and needs no other assignment, why should I declare this
> member not as const?
> 
> In the example I know exactly that I assign only one time a name
> to this struct, so why I should not declare it as const?
> 
> Other example: you have a unique birthday date. This is const you
> cannot change it like a name or a telephone number. So if you
> have a Person struct which holds any data of a single people, you
> won't declare the date as const? I would. And I had expected that
> this is normal behaviour.

Once something is const, you _cannot_ change it. C++ lets you cast away const 
and mutate things, meaning that they aren't really const. D doesn't allow 
that. Casting away const and mutating a variable is undefined behavior. D has 
no mutable keyword. D's const is also transitive, meaning that once something 
is const, everything within it is const (e.g. once you declare a container 
const, _every_ element inside it is const as well). So, any and all operations 
which would involve mutating a const variable are illegal - including mutating 
something which a const variable refers to, since _everything_ it refers to is 
const.

With structs, this has the effect that once one member variable is const, you 
can never again reassign the whole thing. You can assign to its non-const 
members but not the whole thing.

In this particular case, you're dealing with an AA. Depending on the AA's 
implementation, it should be possible to initialize tests[4] and then never 
assign to it again, but that's problematic due to rehashing (hash table's 
_need_ to be able to move objects around), and the current AA implementation 
is fairly poor anyway. So, it ends up default-initializing the value and 
_then_ assigning it, which doesn't work if you can't reassign the value. It 
shouldn't be doing that. It's a bug, and it causes problems with stuff like 
exceptions. For instance, if you have

aa[key] = func();

and func throws, then aa ends up with a default-initialized value at key:

http://d.puremagic.com/issues/show_bug.cgi?id=3825

druntime's AA implementation needs a fair bit of work. H.S. Teoh is working on 
a better implementation, but who knows when we'll have it. We just have to put 
up with buggy corner cases until then unfortunately (though at least AA's work 
just fine most of the time).

I don't know if this particular use case will ever work though, because it 
makes it so that the struct can never be reassigned, and I'm not sure that 
it's at all reasonable for an AA to never be able to reassign its values. Yes, 
initialization should work (unlike now), but rehashing needs to move values 
around, and hash tables have to be able to rehash when they get full enough, 
meaning that being able to reassign elements will probably be required.

- Jonathan M Davis
September 10, 2012
Re: const attribute makes whole element const?
On 09/10/2012 02:05 AM, Namespace wrote:
> I had never problems with that in C++.

clang++ sez:
error: cannot define the implicit default assignment operator for 'S', 
because non-static const member 'x' can't use default assignment operator

> If I have members which are const because they are assigned only one
> time and needs no other assignment, why should I declare this member not
> as const?
>

You can, but then you have to provide your own assignment operator and
you have to work around the aforementioned bug that implies the
assignment operator is not invoked for associative array index
assignments.

> In the example I know exactly that I assign only one time a name to this
> struct, so why I should not declare it as const?
>
> Other example: you have a unique birthday date. This is const you cannot
> change it like a name or a telephone number.

Therefore I cannot be default-assigned to.
September 10, 2012
Re: const attribute makes whole element const?
On 2012-09-10 02:05, Namespace wrote:
> I had never problems with that in C++.
> If I have members which are const because they are assigned only one
> time and needs no other assignment, why should I declare this member not
> as const?
>
> In the example I know exactly that I assign only one time a name to this
> struct, so why I should not declare it as const?

Perhaps declare "Name" as private and create a property getter for the 
field. I think this is a bit annoying as well, it worked in D1.

-- 
/Jacob Carlborg
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home