www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Interior immutability and rvalues

reply maik klein <maikklein googlemail.com> writes:
There are two things that bothered me for quite some time

Interior immutability:

Consider a something like this

https://dpaste.dzfl.pl/fa5be84d26bc

The implementation is totally wrong and it doesn't make sense, 
but it shows that Rc can not be const/immutable because at least 
"dup" needs to increment the counter.

Is it possible to express that Rc should be mutable but the value 
that it wraps should be either mutable or const/immutable?

Rvalues and forwarding:

The problem is that when you pass an rvalue to a function you 
lose the information that is an rvalue. There is nothing like 
std::forward from c++ that I am aware of.

That becomes a problem when I use variadics with non copyable 
types. I need to call move on types that can not be copied.

I guess what I could do is to use 
https://dlang.org/phobos/std_traits.html#hasElaborateCopyConstructor to detect
which types in the variadic args are actually non copyable and then call .move
on them.

Is this how you would do it? The use case would be something like 
this

void test(Args...)(Args args){
     someOtherTest(args); // doesn't work because args contains 
some non copyable types
}

void test(Args...)(Args args){
     someOtherTest(mixin forward!(args));
}

//expands to

void test(Args...)(Args args){
     someOtherTest(args[0].move, args[1], args[2]);
}
Jul 15 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 07/15/2016 10:29 AM, maik klein wrote:
 There are two things that bothered me for quite some time

 Interior immutability:

 Consider a something like this

 https://dpaste.dzfl.pl/fa5be84d26bc

 The implementation is totally wrong and it doesn't make sense, but it
 shows that Rc can not be const/immutable because at least "dup" needs to
 increment the counter.

 Is it possible to express that Rc should be mutable but the value that
 it wraps should be either mutable or const/immutable?
Sure. Just instantiate Rc with a const/immutable T. I.e., write `Rc!(const int)` instead of `const Rc!int`. Or with auto and makeRc: `auto rc = makeRc(immutable int(5));`.
 Rvalues and forwarding:

 The problem is that when you pass an rvalue to a function you lose the
 information that is an rvalue. There is nothing like std::forward from
 c++ that I am aware of.
When you pass an rvalue to a function, the parameter inside the function is still an lvalue. The argument being an rvalue just means that you can't pass it in a ref parameter.
 That becomes a problem when I use variadics with non copyable types. I
 need to call move on types that can not be copied.
Ok, not being copyable is the problem.
 I guess what I could do is to use
 https://dlang.org/phobos/std_traits.html#hasElaborateCopyConstructor to
 detect which types in the variadic args are actually non copyable and
 then call .move on them.

 Is this how you would do it? The use case would be something like this

 void test(Args...)(Args args){
      someOtherTest(args); // doesn't work because args contains some non
 copyable types
 }

 void test(Args...)(Args args){
      someOtherTest(mixin forward!(args));
 }

 //expands to

 void test(Args...)(Args args){
      someOtherTest(args[0].move, args[1], args[2]);
 }
If args[0] can be moved, can args[1] and args[2] be moved, too? I mean, can you just move everything without testing for hasElaborateCopyConstructor? Just a thought.
Jul 15 2016
parent reply maik klein <maikklein googlemail.com> writes:
On Friday, 15 July 2016 at 12:05:47 UTC, ag0aep6g wrote:
 On 07/15/2016 10:29 AM, maik klein wrote:
 [...]
Sure. Just instantiate Rc with a const/immutable T. I.e., write `Rc!(const int)` instead of `const Rc!int`. Or with auto and makeRc: `auto rc = makeRc(immutable int(5));`.
 [...]
When you pass an rvalue to a function, the parameter inside the function is still an lvalue. The argument being an rvalue just means that you can't pass it in a ref parameter.
 [...]
Ok, not being copyable is the problem.
 [...]
If args[0] can be moved, can args[1] and args[2] be moved, too? I mean, can you just move everything without testing for hasElaborateCopyConstructor? Just a thought.
Thanks I didn't know that you could have type qualifiers inside templates, D still surprises me sometimes. I don't think it is practical to call move on "everything", for example maybe you just want to pass a `ref` or a `class`.
Jul 15 2016
parent ag0aep6g <anonymous example.com> writes:
On 07/15/2016 02:51 PM, maik klein wrote:
 Thanks I didn't know that you could have type qualifiers inside
 templates, D still surprises me sometimes.
Qualifiers are part of the type. So wherever you can have a type, you can have a qualified type.
 I don't think it is practical to call move on "everything", for example
 maybe you just want to pass a `ref` or a `class`.
Does move do something bad with class references? I would expect it to just copy the reference, maybe null the original. I'm not sure what you mean by passing a ref. ref is specified in the signature of the called function. So it depends on someOtherTest if the argument is passed by ref, and you have to check that if you don't know the signature beforehand. But it doesn't matter if the variable is copyable or not.
Jul 15 2016