www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - function not callable using struct constructor

reply "alex burton" <alexibu.remove me.com> writes:
struct Foo
{
};

void bar(ref Foo f)
{
}

void main()
{
	bar(Foo());		//Error: function test.bar (ref Foo f) is not 
callable using argument types (Foo)
}

I get the above error with 2.064 not with 2.060.
Is it a bug ?

Is it a feature ?
If so :
Why can't I take a non const ref to a temp struct - It might look 
a bit silly but I might be doing it to avoid copying.

I could still do this :

void main()
{
	Foo f = Foo();
	bar(f);
}

Which is equivalent AFAIK
Jan 02 2014
next sibling parent reply "alex burton" <alexibu.remove me.com> writes:
Also: I couldn't find how to download old versions to make a 
better report on the version it was introduced in.

Links to old versions in the changelog point to the current 
version download.
Jan 02 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-01-03 04:14, alex burton wrote:
 Also: I couldn't find how to download old versions to make a better
 report on the version it was introduced in.

 Links to old versions in the changelog point to the current version
 download.

DVM is a great tool for installing older versions of DMD. I just announced a new release: http://forum.dlang.org/thread/la690h$44u$1 digitalmars.com#post-la690h:2444u:241:40digitalmars.com -- /Jacob Carlborg
Jan 03 2014
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, January 03, 2014 03:13:12 alex burton wrote:
 struct Foo
 {
 };
 
 void bar(ref Foo f)
 {
 }
 
 void main()
 {
 bar(Foo()); //Error: function test.bar (ref Foo f) is not
 callable using argument types (Foo)
 }
 
 I get the above error with 2.064 not with 2.060.
 Is it a bug ?
 
 Is it a feature ?
 If so :
 Why can't I take a non const ref to a temp struct - It might look
 a bit silly but I might be doing it to avoid copying.
 
 I could still do this :
 
 void main()
 {
 Foo f = Foo();
 bar(f);
 }
 
 Which is equivalent AFAIK

ref parameters only accept lvalues. Foo() creates a temporary and is not an lvalue. If you want a function to accept rvalues, it has to not take its argument by ref. If you want to avoid copying lvalues and still accept rvalues, then you need to overload the function (one which takes ref and one which doesn't). And unlike in C++, constness has no effect on whether ref accepts rvalues. ref only ever accepts lvalues. However, in the case of rvalues, ref doesn't save you anything performance- wise. No copy will occur. Rather, because it's an rvalue, it can just move it into the function's parameter rather than copying it. ref only saves you copying with lvalues. - Jonathan M Davis
Jan 02 2014
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 3 January 2014 at 03:13:13 UTC, alex burton wrote:
 struct Foo
 {
 };

 void bar(ref Foo f)
 {
 }

 void main()
 {
 	bar(Foo());		//Error: function test.bar (ref Foo f) is not 
 callable using argument types (Foo)
 }

 I get the above error with 2.064 not with 2.060.
 Is it a bug ?

 Is it a feature ?
 If so :
 Why can't I take a non const ref to a temp struct - It might 
 look a bit silly but I might be doing it to avoid copying.

 I could still do this :

 void main()
 {
 	Foo f = Foo();
 	bar(f);
 }

 Which is equivalent AFAIK

ref. This variable is then an lvalue and is passed by ref to the functions. But all versions after dmd 2.060 do not. What you are searching for is auto ref, but this only works with templates. I had several discussions (and also a DIP) and you will find many many more, that we need auto ref even for non templates. You will hear from Jonathan, Walter and Andrei that it will come *some day*. What you have to do is to overload both: ref and none ref. The compiler chooses the right functions for you, so you have no copies.
Jan 02 2014
prev sibling next sibling parent "alex burton" <alexibu.remove me.com> writes:
On Friday, 3 January 2014 at 03:59:50 UTC, Jonathan M Davis wrote:
 On Friday, January 03, 2014 03:13:12 alex burton wrote:
 struct Foo
 {
 };
 
 void bar(ref Foo f)
 {
 }
 
 void main()
 {
 bar(Foo()); //Error: function test.bar (ref Foo f) is not
 callable using argument types (Foo)
 }
 
 I get the above error with 2.064 not with 2.060.
 Is it a bug ?
 
 Is it a feature ?
 If so :
 Why can't I take a non const ref to a temp struct - It might 
 look
 a bit silly but I might be doing it to avoid copying.
 
 I could still do this :
 
 void main()
 {
 Foo f = Foo();
 bar(f);
 }
 
 Which is equivalent AFAIK

ref parameters only accept lvalues. Foo() creates a temporary and is not an lvalue. If you want a function to accept rvalues, it has to not take its argument by ref. If you want to avoid copying lvalues and still accept rvalues, then you need to overload the function (one which takes ref and one which doesn't). And unlike in C++, constness has no effect on whether ref accepts rvalues. ref only ever accepts lvalues. However, in the case of rvalues, ref doesn't save you anything performance- wise. No copy will occur. Rather, because it's an rvalue, it can just move it into the function's parameter rather than copying it. ref only saves you copying with lvalues. - Jonathan M Davis

Thanks for this, although I tested in 2.064 and the above code works using void bar(in Foo f), which would seem to contracdict "constness has no effect on whether ref accepts rvalues" if I understand it correctly. After looking at the asm, it appears that the compiler doesn't copy the struct when using a void bar(Foo f), but also can avoid copying if a second function like bar is called from bar. It appears that passing by value is what I need, and I should trust the compiler.
Jan 03 2014
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, January 03, 2014 10:06:49 alex burton wrote:
 On Friday, 3 January 2014 at 03:59:50 UTC, Jonathan M Davis wrote:
 On Friday, January 03, 2014 03:13:12 alex burton wrote:
 struct Foo
 {
 };
 
 void bar(ref Foo f)
 {
 }
 
 void main()
 {
 bar(Foo()); //Error: function test.bar (ref Foo f) is not
 callable using argument types (Foo)
 }
 
 I get the above error with 2.064 not with 2.060.
 Is it a bug ?
 
 Is it a feature ?
 If so :
 Why can't I take a non const ref to a temp struct - It might
 look
 a bit silly but I might be doing it to avoid copying.
 
 I could still do this :
 
 void main()
 {
 Foo f = Foo();
 bar(f);
 }
 
 Which is equivalent AFAIK

ref parameters only accept lvalues. Foo() creates a temporary and is not an lvalue. If you want a function to accept rvalues, it has to not take its argument by ref. If you want to avoid copying lvalues and still accept rvalues, then you need to overload the function (one which takes ref and one which doesn't). And unlike in C++, constness has no effect on whether ref accepts rvalues. ref only ever accepts lvalues. However, in the case of rvalues, ref doesn't save you anything performance- wise. No copy will occur. Rather, because it's an rvalue, it can just move it into the function's parameter rather than copying it. ref only saves you copying with lvalues. - Jonathan M Davis

Thanks for this, although I tested in 2.064 and the above code works using void bar(in Foo f), which would seem to contracdict "constness has no effect on whether ref accepts rvalues" if I understand it correctly.

in on a paremeter is the same as const scope and has nothing to do with ref. And since scope currently only has any effect on delegates, your declaration is effectively identical to void bar(const Foo f);
 After looking at the asm, it appears that the compiler doesn't
 copy the struct when using a void bar(Foo f), but also can avoid
 copying if a second function like bar is called from bar.
 
 It appears that passing by value is what I need, and I should
 trust the compiler.

D was specifically designed so that the compiler could avoid copying structs as much as possible. In principle, if the compiler can do a move, it will (though it's quite likely that there are places where it doesn't yet do a move where it should, since the implementation isn't perfect). http://stackoverflow.com/questions/6884996/questions-about-postblit-and-move-semantics - Jonathan M Davis
Jan 03 2014