www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - rvalue based copy

reply "matovitch" <camille.brugel laposte.net> writes:
Hi,

Surely I am misunderstanding something.

I got something like this :

struct S
{
     void opAssign(const ref s)
     {
         //...
     }
}

S genS()
{
     S s;
     //...
     return s;
}

main()
{
     S s;
     s = genS();
}

DMD says : ...opAssign (ref const(S) point) is not callable using 
argument types (S).

Then how to do what I wanna do ? Why doesn't this works ? (I am 
gessing ref argument explitly means no rvalue)

Thanks in advance for your help ! :)
Mar 30 2015
next sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
The title should be assignement not copy.
Mar 30 2015
parent "matovitch" <camille.brugel laposte.net> writes:
void opAssign(const ref s) should be void opAssign(const ref S s) 
btw and btw bis, I should probably make it const ref 
SopAssign(const ref S s)  :/ I stop flooding there.
Mar 30 2015
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 March 2015 at 17:09:14 UTC, matovitch wrote:
(I am gessing ref argument explitly means no rvalue)
That's right. I'd first say don't use ref, just use "const S" and it will work and probably do what you need efficiently. If you do want it to be ref though, rvalues aren't allowed unless you make it "auto ref" which needs to be a template: // this will work, second set of () makes it a template // then auto ref makes it use ref for lvalues and non-ref for rvalues // automatially void opAssign()(const auto ref S s) { //... }
Mar 30 2015
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 17:14:27 UTC, Adam D. Ruppe wrote:
 On Monday, 30 March 2015 at 17:09:14 UTC, matovitch wrote:
(I am gessing ref argument explitly means no rvalue)
That's right. I'd first say don't use ref, just use "const S" and it will work and probably do what you need efficiently.
Yes but you know what they say does it really do a copy of the struct or is the compiler smart enougth most of the time to avoid copy. (I think it's called return value optimization).
 If you do want it to be ref though, rvalues aren't allowed 
 unless you make it "auto ref" which needs to be a template:

 // this will work, second set of () makes it a template
 // then auto ref makes it use ref for lvalues and non-ref for 
 rvalues
 // automatially
     void opAssign()(const auto ref S s)
     {
         //...
     }
Why is this only restricted to templates ?
Mar 30 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 March 2015 at 17:20:30 UTC, matovitch wrote:
 Yes but you know what they say does it really do a copy of the 
 struct or is the compiler smart enougth most of the time to 
 avoid copy. (I think it's called return value optimization).
Copying isn't necessarily a problem, for small structs it is more efficient to copy than passing by ref. But the return value optimization *is* typically done, yes.
 Why is this only restricted to templates ?
It makes two versions of the function, like overloading on the two types of arguments automatically.
Mar 30 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 3/30/15 1:09 PM, matovitch wrote:
 Hi,

 Surely I am misunderstanding something.

 I got something like this :

 struct S
 {
      void opAssign(const ref s)
      {
          //...
      }
 }

 S genS()
 {
      S s;
      //...
      return s;
 }

 main()
 {
      S s;
      s = genS();
 }

 DMD says : ...opAssign (ref const(S) point) is not callable using
 argument types (S).

 Then how to do what I wanna do ? Why doesn't this works ? (I am gessing
 ref argument explitly means no rvalue)

 Thanks in advance for your help ! :)
One solution is to overload void opAssign(ref const S s) {...} void opAssign(const S s) {...} lvalues will go into the ref version, rvalues into the non-ref. There won't be any copying of data, so you still save a postblit and copying on the stack. But you have to repeat the implementation. Another possibility is to use auto ref, but that requires a template. Annoying as this is (and blatantly awkward), it saves you from having to implement twice: void opAssign(T)(auto ref const T s) if(is(T == S)) {...} -Steve
Mar 30 2015
next sibling parent "anonymous" <anonymous example.com> writes:
On Monday, 30 March 2015 at 17:21:53 UTC, Steven Schveighoffer 
wrote:
 One solution is to overload

 void opAssign(ref const S s) {...}
 void opAssign(const S s) {...}

 lvalues will go into the ref version, rvalues into the non-ref. 
 There won't be any copying of data, so you still save a 
 postblit and copying on the stack.

 But you have to repeat the implementation.
You can call the ref version from the non-ref version: void opAssign(ref const S s) {...} void opAssign(const S s) {opAssign(s); /* calls the ref version */} Of course, only do this when the ref version doesn't store &s.
Mar 30 2015
prev sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 17:21:53 UTC, Steven Schveighoffer 
wrote:
  Annoying as this is (and blatantly awkward), it saves
 you from having to implement twice:

 void opAssign(T)(auto ref const T s) if(is(T == S)) {...}
Yep, this seems awkward to me too thought according to Adam one can do : void opAssign()(auto ref const S s) {...}
Mar 30 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 3/30/15 1:42 PM, matovitch wrote:
 On Monday, 30 March 2015 at 17:21:53 UTC, Steven Schveighoffer wrote:
   Annoying as this is (and blatantly awkward), it saves
 you from having to implement twice:

 void opAssign(T)(auto ref const T s) if(is(T == S)) {...}
Yep, this seems awkward to me too thought according to Adam one can do : void opAssign()(auto ref const S s) {...}
Yeah, if Adam says it works, it probably does. I thought it didn't, but I think it's only types that don't allow you to omit the compile-time parameters, not functions. -Steve
Mar 30 2015