www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Variadic function parameters passed by move

reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
If I have a variadic function

f(Rs...)(Rs ranges)
{
     g(ranges);
}

that calls

g(Rs...)(Rs ranges)
{
     // use ranges
}

and all or some of the elements in `ranges` are non-copyable can 
I somehow move them at the call of `g` inside of `f`.

I've tried

f(Rs...)(Rs ranges)
{
     import std.algorithm.mutation : move;
     g(move(ranges));
}

but that does't work.
Dec 21 2016
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/21/2016 12:27 PM, Nordlöw wrote:
 If I have a variadic function

 f(Rs...)(Rs ranges)
 {
     g(ranges);
 }

 that calls

 g(Rs...)(Rs ranges)
 {
     // use ranges
 }

 and all or some of the elements in `ranges` are non-copyable can I
 somehow move them at the call of `g` inside of `f`.

 I've tried

 f(Rs...)(Rs ranges)
 {
     import std.algorithm.mutation : move;
     g(move(ranges));
 }

 but that does't work.
At least compiles. :) void f(Rs...)(Rs ranges) { import std.functional: forward; g(forward!ranges); } void g(Rs...)(Rs ranges) { // use ranges } struct S { disable this(this); } void main() { f(1, S()); } Ali
Dec 21 2016
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 21 December 2016 at 21:02:17 UTC, Ali Çehreli wrote:
 void f(Rs...)(Rs ranges)
 {
     import std.functional: forward;
     g(forward!ranges);
Interesting. How does this differ from std.algorithm.mutation.move() when R.length is 1? Why do we have both `move` and `forward`, then?
Dec 21 2016
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/21/2016 02:59 PM, Nordlöw wrote:
 On Wednesday, 21 December 2016 at 21:02:17 UTC, Ali Çehreli wrote:
 void f(Rs...)(Rs ranges)
 {
     import std.functional: forward;
     g(forward!ranges);
Interesting. How does this differ from std.algorithm.mutation.move() when R.length is 1? Why do we have both `move` and `forward`, then?
Here is what I understand after glancing the documentation again: * 'move' is for moving state, which may necessitate destroying the source if leaving it behind can cause harm. For example, if the object has a destructor or post-blit, then the source should be "silenced" :) to prevent doing it twice. * As an added bonus, 'move' seems to be one spot (the only?) that D validates that a struct object does not have internal pointers. * 'forward' is for forwarding arguments to functions. It seems to an answer to "perfect forwarding" that I know from C++: maintain by-ref'ness of arguments when forwarding them to other functions. Ali
Dec 21 2016
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, December 21, 2016 20:27:47 Nordlöw via Digitalmars-d-learn 
wrote:
 If I have a variadic function

 f(Rs...)(Rs ranges)
 {
      g(ranges);
 }

 that calls

 g(Rs...)(Rs ranges)
 {
      // use ranges
 }

 and all or some of the elements in `ranges` are non-copyable can
 I somehow move them at the call of `g` inside of `f`.

 I've tried

 f(Rs...)(Rs ranges)
 {
      import std.algorithm.mutation : move;
      g(move(ranges));
 }

 but that does't work.
Given that ref isn't involved, assuming that nothing else after the call to g references ranges, the compiler should move the values in ranges when it calls g, so I would have hoped that the compiler would then allow you to call g with some of the values being non-copyable, but maybe it's not that forgiving right now for some reason. I can't actually test anything at the moment though, so I don't know what it will and won't actually allow you to do - just what it should be able to allow you to do given what it does with implicit moves. - Jonathan M Davis
Dec 21 2016
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 21 December 2016 at 21:09:41 UTC, Jonathan M Davis 
wrote:
 Given that ref isn't involved, assuming that nothing else after 
 the call to g references ranges, the compiler should move the 
 values in ranges when it calls g, so I would have hoped that 
 the compiler would then allow you to call g with some of the 
 values being non-copyable, but maybe it's not that forgiving 
 right now for some reason. I can't actually test anything at 
 the moment though, so I don't know what it will and won't 
 actually allow you to do - just what it should be able to allow 
 you to do given what it does with implicit moves.
My plan: https://github.com/dlang/phobos/pull/4971
Dec 21 2016
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 21 December 2016 at 23:11:02 UTC, Nordlöw wrote:
 Given that ref isn't involved, assuming that nothing else 
 after the call to g references ranges, the compiler should 
 move the values in ranges when it calls g
Yes, DMD should automatically convert the last reference of a value expression to an r-value. This, most likely, involves calling doCopyOrMove() on the correct AST node somewhere in dmd/src/expression.d. But I haven't figure out how to do this. I have and idea outlined here: https://github.com/nordlow/dmd/commit/d3053e7801e340541bba32172718c2bb3de966c0 But I need feedback from the kernel developers on how go forward with this. Specifically the visitor that finds the last reference of a symbol that can be passed by move (non-reference) parameter in current function (scope). Do you have any clue on how to most easily find detect whether a SymbolExpression is the last reference to that symbol in the scope of the symbol definition, Jonathan? If this gets fixed we will have yet another way of programming with ranges in D that will require neither RC nor GC!
Dec 21 2016
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, December 21, 2016 23:18:29 Nordlöw via Digitalmars-d-learn 
wrote:
 Do you have any clue on how to most easily find detect whether a
 SymbolExpression is the last reference to that symbol in the
 scope of the symbol definition, Jonathan?
Sorry, but my knowledge of dmd's internals is pretty poor. I'm somewhat familiar with the lexer, but that's about it. - Jonathan M Davis
Jan 02 2017