View mode: basic / threaded / horizontal-split · Log in · Help
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 07:41:32 UTC, Simen Kjaeraas wrote:
> On Thu, 03 May 2012 00:38:35 +0200, Namespace 
> <rswhite4@googlemail.com> wrote:
>
>> I'm not very skillful in such "template" stories. Maybe 
>> someone can help me?
>
> The main problem here is your opCast is non-const. (it's always 
> an indication of
> const problems when DMD says "<X> is not callable using 
> argument types ()")
>
> Solution:
>
> class A {
>     int val;
>
>     alias val this;
>
>     T opCast(T : Object)() {
>         writeln("FOO");
>
>         return to!(T)(this);
>     }
>
>     // Add this
>     T opCast(T : Object)() const {
>         writeln("FOO");
>
>         return to!(T)(this);
>     }
> }

Hm, simple. Thank you, as long as the bug isn't fixed, this has 
to be enough. :)
May 03, 2012
Re: cannot cast
> If you want to restrict opCast, then use a template constraint, 
> constraining
> it to what you want to work with it. Also, casting away const 
> is generally a
> bad idea in D. Casting away const and mutating a variable is an 
> _extremely_
> bad idea. You _really_ shouldn't be doing it. So, the fact that 
> you _have_ a
> function which is specifically trying to cast away const is 
> almost certainly
> _not_ a good idea.
>
> http://stackoverflow.com/questions/4219600/logical-const-in-d
>
>
> - Jonathan M Davis

So, you mean that if i declared any parameter as const, it have 
to stay const all the time?
What would you do, if you need in a special case a mutable 
version or must change the object itself?
Because there is no "mutable" keyword in D you have to cast away 
the constness.
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 07:41:32 UTC, Simen Kjaeraas wrote:
> On Thu, 03 May 2012 00:38:35 +0200, Namespace 
> <rswhite4@googlemail.com> wrote:
>
>> I'm not very skillful in such "template" stories. Maybe 
>> someone can help me?
>
> The main problem here is your opCast is non-const. (it's always 
> an indication of
> const problems when DMD says "<X> is not callable using 
> argument types ()")
>
> Solution:
>
> class A {
>     int val;
>
>     alias val this;
>
>     T opCast(T : Object)() {
>         writeln("FOO");
>
>         return to!(T)(this);
>     }
>
>     // Add this
>     T opCast(T : Object)() const {
>         writeln("FOO");
>
>         return to!(T)(this);
>     }
> }

My tests are failed, but isn't it possible, to reduce both 
methods to one with the inout keyword?
May 03, 2012
Re: cannot cast
On 05/03/2012 09:33 AM, Namespace wrote:
> On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote:
>> Other, shorter example:
>>
>> [code]
>> import std.stdio, std.traits;
>>
>> class A {
>> int val;
>>
>> alias val this;
>>
>> T opCast(T : Object)() {
>> writeln("FOO");
>>
>> return to!(T)(this);
>> }
>> }
>>
>> class B : A {
>>
>> }
>>
>> T to(T : Object, U : Object)(const U obj) {
>> return *(cast(T*) &obj);
>> }
>>
>> T const_cast(T)(const T obj) {
>> return cast(T) obj;
>> }
>>
>> void main () {
>> A a = new B();
>> a.val = 42;
>>
>> writefln("a.val: %d", a.val);
>>
>> B* b = cast(B*) &a;
>> writefln("*b.val: %d", b.val);
>>
>> B b1 = to!(B)(a);
>> writefln("b1.val: %d", b1.val);
>>
>> B b2 = cast(B) a;
>> writefln("b2.val: %d", b2.val);
>>
>> const B b3 = cast(B) a;
>>
>> B b4 = const_cast(b3);
>> }
>> [/code]
>>
>> print:
>>
>> alias_this_impl.d(24): Error: function
>> alias_this_impl.A.opCast!(B).opCast () is
>> not callable using argument types ()
>> alias_this_impl.d(44): Error: template instance
>> alias_this_impl.const_cast!(B) e
>> rror instantiating
>>
>> I'm not very skillful in such "template" stories. Maybe someone can
>> help me?
>
> Solved with
>
> T const_cast(T)(const T obj) {
> return to!(T)(obj);
> }
>
> But i think that there must exist a more nicer way to cast away const,
> isn't there?
>
> To cast away "const" with a simple cast to "T" fails (see my post
> above), because i have no idea, how i can restrict my opCast. So i have
> to convert it again with "to". Do some of you have any ideas how i can
> restrict my opCast, so my const_cast doesn't match it, e.g. with some
> template magic?




Unqual k├Ânnen Sie finden in std.traits.


template Unqual(T)
{
    version (none) // Error: recursive alias declaration @@@BUG1308@@@
    {
             static if (is(T U == const U)) alias Unqual!U Unqual;
        else static if (is(T U == immutable U)) alias Unqual!U Unqual;
        else static if (is(T U == inout U)) alias Unqual!U Unqual;
        else static if (is(T U == shared U)) alias Unqual!U Unqual;
        else alias T Unqual;
    }
    else // workaround
    {
             static if (is(T U == shared(const U))) alias U Unqual;
        else static if (is(T U == const U )) alias U Unqual;
        else static if (is(T U == immutable U )) alias U Unqual;
        else static if (is(T U == inout U )) alias U Unqual;
        else static if (is(T U == shared U )) alias U Unqual;
        else alias T Unqual;
    }
}

unittest
{
    static assert(is(Unqual!(int) == int));
    static assert(is(Unqual!(const int) == int));
    static assert(is(Unqual!(immutable int) == int));
    static assert(is(Unqual!(inout int) == int));
    static assert(is(Unqual!(shared int) == int));
    static assert(is(Unqual!(shared(const int)) == int));
    alias immutable(int[]) ImmIntArr;
    static assert(is(Unqual!(ImmIntArr) == immutable(int)[]));
}
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote:
> So, you mean that if i declared any parameter as const, it have 
> to stay const all the time?

Yes. const = you can't change. Changing it is invalid behavior. 
Imagine const/immutable as bits in readonly memory and you'll 
have to right mindset.

> What would you do, if you need in a special case a mutable 
> version or must change the object itself?
> Because there is no "mutable" keyword in D you have to cast 
> away the constness.

In what way do you mean? If it's something you honestly _need_ to 
change and it's const, then maybe throwing an exception would be 
appropriate.
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 08:46:26 UTC, Chris Cain wrote:
> On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote:
>> So, you mean that if i declared any parameter as const, it 
>> have to stay const all the time?
>
> Yes. const = you can't change. Changing it is invalid behavior. 
> Imagine const/immutable as bits in readonly memory and you'll 
> have to right mindset.
>
>> What would you do, if you need in a special case a mutable 
>> version or must change the object itself?
>> Because there is no "mutable" keyword in D you have to cast 
>> away the constness.
>
> In what way do you mean? If it's something you honestly _need_ 
> to change and it's const, then maybe throwing an exception 
> would be appropriate.

I thought that const = "cannot change directly" and immutable 
stands for "cannot change all the time". If not, why exist both 
storage classes beside?
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 08:54:48 UTC, Namespace wrote:
> I thought that const = "cannot change directly" and immutable 
> stands for "cannot change all the time". If not, why exist both 
> storage classes beside?

const = you (as in, your view of the data as you're working with 
it) can't change
immutable = no one can change it ... as in, there exists no view 
of the data that can mutate it.

It's a subtle distinction. In fact, you can be handed a "const" 
and it's actually immutable underneath. And since immutable data 
can actually be stored in read only memory...
May 03, 2012
Re: cannot cast
On Thursday, 3 May 2012 at 09:00:08 UTC, Chris Cain wrote:
> const = you (as in, your view of the data as you're working 
> with it) can't change

Actually, let me be even clearer with this... I mean _you_ cannot 
change it, but it might be changed by someone else's view, in 
which case it would appear to change in your view ... but not by 
any interaction you make with it.

This means concretely that anything you do with the object will 
have no effect on its bit representation in memory, although the 
bit representation in memory might be changed by other 
threads/processes/views.
May 03, 2012
Re: cannot cast
On Thursday, May 03, 2012 10:54:47 Namespace wrote:
> On Thursday, 3 May 2012 at 08:46:26 UTC, Chris Cain wrote:
> > On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote:
> >> So, you mean that if i declared any parameter as const, it
> >> have to stay const all the time?
> > 
> > Yes. const = you can't change. Changing it is invalid behavior.
> > Imagine const/immutable as bits in readonly memory and you'll
> > have to right mindset.
> > 
> >> What would you do, if you need in a special case a mutable
> >> version or must change the object itself?
> >> Because there is no "mutable" keyword in D you have to cast
> >> away the constness.
> > 
> > In what way do you mean? If it's something you honestly _need_
> > to change and it's const, then maybe throwing an exception
> > would be appropriate.
> 
> I thought that const = "cannot change directly" and immutable
> stands for "cannot change all the time". If not, why exist both
> storage classes beside?

An immutable variable can never be changed by any reference to that data. It's 
also implicitly shared across threads (since it can never change).

If a const variable is a value type, then there really isn't any difference 
between const and immutable. If it's a reference type, then it just indicates 
that that particular reference cannot alter the data. Another reference may or 
may not be able to (and const is _not_ implicitly shared across threads, 
because the data _can_ change if there are mutable references to it). But if a 
reference is const, it's breaking the type system to cast away const and alter 
the data precisely because the compiler can't know whether that data is 
actually mutable or not. For instance, what if if you did something like

const var = new immutable(A);

var may be const, but it refers to a value which is actually immutable. 
Depending on what the compiler does, mutating var could result in nasty stuff 
like segfaults. In the general case, the compiler has no way of knowing 
whether a const variable is really mutable or immutable underneath. So, 
casting away const and mutating a variable is undefined behavior. As far as the 
compiler is concerned, a variable is _never_ mutated through a const 
reference, and it will optimize code based on that. So, casting away const can 
not only result in segfaults if the data is actually immutable, but it can 
result in incorrect behavior due to optimizations that the compiler makes 
based on the assumption that the variable wouldn't change but which you 
violated by casting away const and mutating the variable.

Unlike immutable, _other_ references to the data may mutate it (and the 
compiler must take that into account when optimizing), but you should never 
try and mutate a const variable. Once something is const, _leave_ it that way. 
If you need a mutable reference to it, then you need to get one which was 
mutable in the first place rather than coming from the const reference through 
casting.

Casting away const is legal, because D is a systems language, but actually 
mutating the variable after casting away const is undefined behavior, so you 
should never do it unless you really know what you're doing.

http://stackoverflow.com/questions/4219600/logical-const-in-d

- Jonathan M Davis
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home