www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - does cast make an lvalue appear to be an rvalue

reply "Daniel Davidson" <nospam spam.com> writes:
The code below fails to compile due to the last line. I was 
hoping casting away immutable would allow the call to foo. I 
think it is not accepted because of the rval to ref issue. If 
that is the case, how can foo be called by casting?

I'm not a fan of casting but I'm finding cases where it is the 
only recourse to create immutable data using impure functions 
that should be pure.

Thanks
Dan

import std.conv;

struct T {
   int[] i;
   string[string] ss;
}

void foo(ref T t) {
}

void main() {
   T t1;
   auto t2 = immutable T();
   foo(t1);
   foo(cast()t2);
}
Oct 16 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 16 October 2013 at 17:05:25 UTC, Daniel Davidson 
wrote:
 import std.conv;

 struct T {
   int[] i;
   string[string] ss;
 }

 void foo(ref T t) {
 }

 void main() {
   T t1;
   auto t2 = immutable T();
   foo(t1);
   foo(cast()t2);
 }
It works as it should. Make a mutable copy of t2 and pass it. Or make foo() accept const. I can't imagine a single legitimate use case for destroying type system in a way you want.
Oct 16 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 17:16:39 UTC, Dicebot wrote:
 It works as it should. Make a mutable copy of t2 and pass it. 
 Or make foo() accept const. I can't imagine a single legitimate 
 use case for destroying type system in a way you want.
How do you propose to make a mutable copy *generically*? I think a legitimate use would be the following. In the construction of S I want to use a T to construct an R. `this(...) immutable {}` prevents initialization of R in this case. Maybe immutable adorning `this()` should mean it is immutable upon the end of the construction, giving the initialization a chance to actually initialize. In the example below a better approach would be to have: R createRFromT(ref const(T) t) pure {...} but with what I'm using from phobos that is not possible. ------------------------------------------------ import std.conv; import std.stdio; struct R { int[] i; string[string] ss; } struct T { int[] i; string[string] ss; } struct S { R r; this(ref const(T) t) immutable { createRFromT(t, r); } } void createRFromT(ref const(T) t, ref R r) { //... } void main() { T t1; auto t2 = immutable T(); auto s = immutable S(t2); }
Oct 16 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
struct S {
   R r;
   this(ref immutable(T) t) immutable {
     r.tupleof = t.tupleof;
   }
}

?
Oct 16 2013
parent "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 17:55:56 UTC, Dicebot wrote:
 struct S {
   R r;
   this(ref immutable(T) t) immutable {
     r.tupleof = t.tupleof;
   }
 }

 ?
Thanks. It is cute - but not so helpful. The example stands. I *need* to call a createRFromT. Their shapes are the same in this simple example because I simplified. Make R look like: struct R { string[string] ss; int[] j; } and the cute trick falls apart. In words, I have an R and I want to make a T. The R is const the T will be immutable because the ctor requires it. But it is technically not immutable until it is initialized.
Oct 16 2013
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 16 October 2013 at 17:50:48 UTC, Daniel Davidson 
wrote:
 On Wednesday, 16 October 2013 at 17:16:39 UTC, Dicebot wrote:
 It works as it should. Make a mutable copy of t2 and pass it. 
 Or make foo() accept const. I can't imagine a single 
 legitimate use case for destroying type system in a way you 
 want.
How do you propose to make a mutable copy *generically*?
Recursively going through the levels of indirection via static introspection and allocating memory for new mutable counter-parts as it goes. Maybe it should belong to Phobos, no idea right now, will know once I ever find the need for it.
Oct 16 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 17:58:41 UTC, Dicebot wrote:
 On Wednesday, 16 October 2013 at 17:50:48 UTC, Daniel Davidson 
 wrote:
 On Wednesday, 16 October 2013 at 17:16:39 UTC, Dicebot wrote:
 It works as it should. Make a mutable copy of t2 and pass it. 
 Or make foo() accept const. I can't imagine a single 
 legitimate use case for destroying type system in a way you 
 want.
How do you propose to make a mutable copy *generically*?
Recursively going through the levels of indirection via static introspection and allocating memory for new mutable counter-parts as it goes. Maybe it should belong to Phobos, no idea right now, will know once I ever find the need for it.
I agree with the sentiment. But as it stands I think a copy should not be necessary. I could make a local mutable R, pass it to createRFromT to get it initialized and then copy it back somehow to the member variable r. That to me is silly. The copy should not be required.
Oct 16 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 16 October 2013 at 18:14:22 UTC, Daniel Davidson 
wrote:
 I agree with the sentiment. But as it stands I think a copy 
 should not be necessary. I could make a local mutable R, pass 
 it to createRFromT to get it initialized and then copy it back 
 somehow to the member variable r. That to me is silly. The copy 
 should not be required.
Then don't use immutable. Root of all problems with immutable comes from trying to use it for something it should never be. `immutable` means "never ever can be accessed with a mutable" with any compiler optimization that may come from that. Any cast is undefined behavior in a form of time bomb. Basically, only thing immutable is good at is to create some potentially shared data and slicing / reading it when needed. If you need the same data but for passing as mutable function argument, you MUST make a copy, there is no safe way around it.
Oct 16 2013
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 16 October 2013 at 17:50:48 UTC, Daniel Davidson 
wrote:
 How do you propose to make a mutable copy *generically*?
You can't. Let alone generically. If I give you an "immutable int* p", how do you copy it to "int* p" ? On Wednesday, 16 October 2013 at 18:11:48 UTC, Daniel Davidson wrote:
 Thanks. It is cute - but not so helpful. The example stands. I 
 *need* to call a createRFromT.

 Their shapes are the same in this simple example because I 
 simplified. Make R look like:

 struct R {
   string[string] ss;
   int[] j;
 }

 and the cute trick falls apart. In words, I have an R and I 
 want to make a T. The R is const the T will be immutable 
 because the ctor requires it. But it is technically not 
 immutable until it is initialized.
The problem is that you are taking a const(R). And you can't assign a const to an immutable. It has nothing to do with initialization. Remember: "const" means *you* promise not to modify the value, whereas immutable means *no one* will modify it ever. Because of this, you can't assign a const to an immutable. For example: int[] a = [1]; const(int)[] c = a; //Legal immutable(int)[] i = c; //Forbidden If that assignment passed, think of what would happen if I wrote: a[0] = 5; On Wednesday, 16 October 2013 at 18:14:22 UTC, Daniel Davidson wrote:
 I agree with the sentiment. But as it stands I think a copy 
 should not be necessary. I could make a local mutable R, pass 
 it to createRFromT to get it initialized and then copy it back 
 somehow to the member variable r. That to me is silly. The copy 
 should not be required.
A copy *might* not be necessary provided building an immutable copy from mutable is actually legal. This is not your case. What you are doing is warping the type system.
Oct 16 2013
next sibling parent "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 19:49:25 UTC, monarch_dodra 
wrote:
 On Wednesday, 16 October 2013 at 17:50:48 UTC, Daniel Davidson 
 wrote:
 How do you propose to make a mutable copy *generically*?
You can't. Let alone generically. If I give you an "immutable int* p", how do you copy it to "int* p" ?
That was my point.
 On Wednesday, 16 October 2013 at 18:11:48 UTC, Daniel Davidson 
 wrote:
 Thanks. It is cute - but not so helpful. The example stands. I 
 *need* to call a createRFromT.

 Their shapes are the same in this simple example because I 
 simplified. Make R look like:

 struct R {
  string[string] ss;
  int[] j;
 }

 and the cute trick falls apart. In words, I have an R and I 
 want to make a T. The R is const the T will be immutable 
 because the ctor requires it. But it is technically not 
 immutable until it is initialized.
The problem is that you are taking a const(R). And you can't assign a const to an immutable. It has nothing to do with initialization.
No I don't think I am. What code are you looking at?
 A copy *might* not be necessary provided building an immutable 
 copy from mutable is actually legal. This is not your case.

 What you are doing is warping the type system.
Based on your previous comment, I don't think you understood the setup.
Oct 16 2013
prev sibling parent "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 19:49:25 UTC, monarch_dodra 
wrote:
 On Wednesday, 16 October 2013 at 17:50:48 UTC, Daniel Davidson 
 wrote:
 How do you propose to make a mutable copy *generically*?
You can't. Let alone generically. If I give you an "immutable int* p", how do you copy it to "int* p" ? On Wednesday, 16 October 2013 at 18:11:48 UTC, Daniel Davidson wrote:
 Thanks. It is cute - but not so helpful. The example stands. I 
 *need* to call a createRFromT.

 Their shapes are the same in this simple example because I 
 simplified. Make R look like:

 struct R {
  string[string] ss;
  int[] j;
 }

 and the cute trick falls apart. In words, I have an R and I 
 want to make a T. The R is const the T will be immutable 
 because the ctor requires it. But it is technically not 
 immutable until it is initialized.
The problem is that you are taking a const(R). And you can't assign a const to an immutable. It has nothing to do with initialization.
Just to clarify: in the code below: createRFromT(t, r) is *not* meant to imply it will just try an assignment. Rather, it reads from t and builds its own data for R. The problem is with initialization - see Simen Kjaeraas response here: http://forum.dlang.org/post/mailman.2241.1381953340.1719.digitalmars-d-learn puremagic.com struct S { R r; this(ref const(T) t) immutable { createRFromT(t, r); } } void createRFromT(ref const(T) t, ref R r) { //... }
Oct 16 2013
prev sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 16 October 2013 at 17:05:25 UTC, Daniel Davidson 
wrote:
 The code below fails to compile due to the last line. I was 
 hoping casting away immutable would allow the call to foo. I 
 think it is not accepted because of the rval to ref issue. If 
 that is the case, how can foo be called by casting?

 I'm not a fan of casting but I'm finding cases where it is the 
 only recourse to create immutable data using impure functions 
 that should be pure.

 Thanks
 Dan

 import std.conv;

 struct T {
   int[] i;
   string[string] ss;
 }

 void foo(ref T t) {
 }

 void main() {
   T t1;
   auto t2 = immutable T();
   foo(t1);
   foo(cast()t2);
 }
foo([cast()t2][0]); (It would be good to have compound literals like in C)
Oct 16 2013
parent "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 16 October 2013 at 18:09:55 UTC, Maxim Fomin wrote:
 On Wednesday, 16 October 2013 at 17:05:25 UTC, Daniel Davidson 
 wrote:
 The code below fails to compile due to the last line. I was 
 hoping casting away immutable would allow the call to foo. I 
 think it is not accepted because of the rval to ref issue. If 
 that is the case, how can foo be called by casting?

 I'm not a fan of casting but I'm finding cases where it is the 
 only recourse to create immutable data using impure functions 
 that should be pure.

 Thanks
 Dan

 import std.conv;

 struct T {
  int[] i;
  string[string] ss;
 }

 void foo(ref T t) {
 }

 void main() {
  T t1;
  auto t2 = immutable T();
  foo(t1);
  foo(cast()t2);
 }
foo([cast()t2][0]); (It would be good to have compound literals like in C)
Haaah - brilliant. Scary, but brilliant.
Oct 16 2013