www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Return by 'ref' problems...

reply Manu <turkeyman gmail.com> writes:
So here's some problems.

I use 'const ref' to pass structs to functions (note: because 'in ref'
doesn't seem to work)
And I often need to return structs by ref too, but I'm having problems:

void test( const ref Thing x ) {} // this works fine. note, 'const ref'
works fine here (in lieu of 'in ref')


struct Thing { }
Thing thing;

const ref Thing func() { return gThing; }

This syntax complains, but it's precisely the same expression I use to pass
an argument in to a function, and it's fine there:
  remedy\modules\hud.d(35):Error: function remedy.hud.func without 'this'
cannot be const/immutable

const ref Thing function() blah = &func;

I need to take a pointer to this function, but It complains when I declare
a 'function' of this type:
  remedy\modules\hud.d(36):Error: variable remedy.hud.blah only parameters
or foreach declarations can be ref   (... what? it works for parameters?)


I try rearranging the syntax to make the first issue stop complaining:

ref const(Thing) func2() { return gThing; } // this seems to work now, but
i don't like the inconsistency...
ref const(Thing) function() blah2 = &func;

Error: variable remedy.hud.blah2 only parameters or foreach declarations
can be ref
May 04 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-04 10:38, Manu wrote:
 So here's some problems.

 I use 'const ref' to pass structs to functions (note: because 'in ref'
 doesn't seem to work)
 And I often need to return structs by ref too, but I'm having problems:

 void test( const ref Thing x ) {} // this works fine. note, 'const ref'
 works fine here (in lieu of 'in ref')


 struct Thing { }
 Thing thing;

 const ref Thing func() { return gThing; }
In this case the function "func" is declared const and not the return type. The reason for this is to allow this: class Foo { const: // All methods will be const } It's possible to do this with all attributes.
 This syntax complains, but it's precisely the same expression I use to
 pass an argument in to a function, and it's fine there:
    remedy\modules\hud.d(35):Error: function remedy.hud.func without
 'this' cannot be const/immutable

 const ref Thing function() blah = &func;
Again this declares the variable const and not the return type. I'm not sure about the "ref" thing. I don't know if function pointers can return by reference, at least not the syntax.
 I need to take a pointer to this function, but It complains when I
 declare a 'function' of this type:
    remedy\modules\hud.d(36):Error: variable remedy.hud.blah only
 parameters or foreach declarations can be ref   (... what? it works for
 parameters?)


 I try rearranging the syntax to make the first issue stop complaining:

 ref const(Thing) func2() { return gThing; } // this seems to work now,
 but i don't like the inconsistency...
 ref const(Thing) function() blah2 = &func;
This is the correct syntax to declare that it returns a const object.
 Error: variable remedy.hud.blah2 only parameters or foreach declarations
 can be ref
Don't know about the reference. -- /Jacob Carlborg
May 04 2012
parent reply Manu <turkeyman gmail.com> writes:
On 4 May 2012 12:52, Jacob Carlborg <doob me.com> wrote:

 On 2012-05-04 10:38, Manu wrote:

 This syntax complains, but it's precisely the same expression I use to
pass an argument in to a function, and it's fine there:
   remedy\modules\hud.d(35):**Error: function remedy.hud.func without
 'this' cannot be const/immutable

 const ref Thing function() blah = &func;
Again this declares the variable const and not the return type. I'm not sure about the "ref" thing. I don't know if function pointers can return by reference, at least not the syntax.
Ah, of course! I didn't spot that >_< Thanks. I suppose technically, 'ref' can lead to the same ambiguity. This must be the core of the problem. ref needs to be supported with parentheses?
May 04 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-04 12:09, Manu wrote:

 Ah, of course! I didn't spot that >_<
 Thanks.

 I suppose technically, 'ref' can lead to the same ambiguity. This must
 be the core of the problem. ref needs to be supported with parentheses?
I'm not sure, since you can't declare a variable as "ref" I think the syntax should work. But the syntax with parentheses should probably work as well, to be consistent with "const". -- /Jacob Carlborg
May 04 2012
next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 11:49:44 UTC, Jacob Carlborg wrote:
 On 2012-05-04 12:09, Manu wrote:

 Ah, of course! I didn't spot that >_<
 Thanks.

 I suppose technically, 'ref' can lead to the same ambiguity. 
 This must
 be the core of the problem. ref needs to be supported with 
 parentheses?
I'm not sure, since you can't declare a variable as "ref" I think the syntax should work. But the syntax with parentheses should probably work as well, to be consistent with "const".
Const can be used with parentheses because it is also a type qualifier in addition to a storage class (for syntactic purposes). All of const, immutable and shared have this dual syntactic existence. 'ref' has several meanings depending on context, but it is never a type qualifier. I think conflating the syntax for the two would mostly bring confusion.
May 04 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 4 May 2012 14:49, Jacob Carlborg <doob me.com> wrote:

 On 2012-05-04 12:09, Manu wrote:

  Ah, of course! I didn't spot that >_<
 Thanks.

 I suppose technically, 'ref' can lead to the same ambiguity. This must
 be the core of the problem. ref needs to be supported with parentheses?
I'm not sure, since you can't declare a variable as "ref" I think the syntax should work. But the syntax with parentheses should probably work as well, to be consistent with "const".
You can declare a variable as ref in the parameter list, that's where the ambiguity could arise, same with const.
May 04 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-04 14:27, Manu wrote:

 You can declare a variable as ref in the parameter list, that's where
 the ambiguity could arise, same with const.
Yes, but I thought this was a variable of some kind and not a parameter. -- /Jacob Carlborg
May 04 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/04/2012 10:38 AM, Manu wrote:
 So here's some problems.

 I use 'const ref' to pass structs to functions (note: because 'in ref'
 doesn't seem to work)
 And I often need to return structs by ref too, but I'm having problems:

 void test( const ref Thing x ) {} // this works fine. note, 'const ref'
 works fine here (in lieu of 'in ref')


 struct Thing { }
 Thing thing;

 const ref Thing func() { return gThing; }

 This syntax complains, but it's precisely the same expression I use to
 pass an argument in to a function, and it's fine there:
    remedy\modules\hud.d(35):Error: function remedy.hud.func without
 'this' cannot be const/immutable

 const ref Thing function() blah = &func;
It is not the same, because it is parsed like const{ ref Thing func() { return gThing; }
 I need to take a pointer to this function, but It complains when I
 declare a 'function' of this type:
    remedy\modules\hud.d(36):Error: variable remedy.hud.blah only
 parameters or foreach declarations can be ref   (... what? it works for
 parameters?)


 I try rearranging the syntax to make the first issue stop complaining:

 ref const(Thing) func2() { return gThing; } // this seems to work now,
 but i don't like the inconsistency...
 ref const(Thing) function() blah2 = &func;

 Error: variable remedy.hud.blah2 only parameters or foreach declarations
 can be ref
This is parsed like ref { const(Thing) function() blah2 = &func; } i.e. it qualifies the variable instead of the type. This should work: const(Thing) function()ref blah2 = &func; Except that it does not, because 'ref' is not currently a valid function 'storage class'. This seems to be an issue that deserves a bug report.
May 04 2012
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 12:45:23 UTC, Timon Gehr wrote:
 This should work:

 const(Thing) function()ref blah2 = &func;

 Except that it does not, because 'ref' is not currently a valid 
 function 'storage class'. This seems to be an issue that 
 deserves a bug report.
For ref functions, 'ref' is part of the return type syntax, much like auto functions. There is no precedent for 'ref' working as a function attribute; it never was one.
May 04 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/04/2012 03:00 PM, Jakob Ovrum wrote:
 On Friday, 4 May 2012 at 12:45:23 UTC, Timon Gehr wrote:
 This should work:

 const(Thing) function()ref blah2 = &func;

 Except that it does not, because 'ref' is not currently a valid
 function 'storage class'. This seems to be an issue that deserves a
 bug report.
For ref functions, 'ref' is part of the return type syntax,
If it was, then ref const(Thing) function() would work.
 much like auto functions.
 There is no precedent for 'ref' working as a function
 attribute; it never was one.
It is an attribute: int x; ref { int foo(){ return x; } int bar(){ return x; } } ref: int qux(){ return x; } static assert(typeof(&qux).stringof == "int function() ref");
May 04 2012
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 14:34:20 UTC, Timon Gehr wrote:
 It is an attribute:

 int x;
 ref {
   int foo(){ return x; }
   int bar(){ return x; }
 }

 ref:

 int qux(){ return x; }

 static assert(typeof(&qux).stringof == "int function() ref");
Thanks, this is news to me! I never noticed that ref was actually a function attribute. The following are legal declaration statements: extern(C) void function() foo; pure void function() bar; // not just linkage attributes So I think it's a plain bug that this isn't: ref void function() foo;
May 04 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/04/2012 04:53 PM, Jakob Ovrum wrote:
 On Friday, 4 May 2012 at 14:34:20 UTC, Timon Gehr wrote:
 It is an attribute:

 int x;
 ref {
     int foo(){ return x; }
     int bar(){ return x; }
 }

 ref:

 int qux(){ return x; }

 static assert(typeof(&qux).stringof == "int function() ref");
Thanks, this is news to me! I never noticed that ref was actually a function attribute. The following are legal declaration statements: extern(C) void function() foo; pure void function() bar; // not just linkage attributes So I think it's a plain bug that this isn't: ref void function() foo;
What would be the meaning of void foo(ref void function() fn) { } ?
May 04 2012
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 14:57:14 UTC, Timon Gehr wrote:
 What would be the meaning of

 void foo(ref void function() fn) { }

 ?
Parameter storage classes can only go before the type, while function attributes can also go after the parameter list (of the function pointer or delegate for this case). So I would think that: void foo(ref void function() fn) { } The above 'foo' would receive a function pointer by reference, while: void foo(void function() ref fn) { } Would receive a function pointer which returns by ref.
May 04 2012
parent reply Manu <turkeyman gmail.com> writes:
On 4 May 2012 18:07, Jakob Ovrum <jakobovrum gmail.com> wrote:

 On Friday, 4 May 2012 at 14:57:14 UTC, Timon Gehr wrote:

 What would be the meaning of

 void foo(ref void function() fn) { }

 ?
Parameter storage classes can only go before the type, while function attributes can also go after the parameter list (of the function pointer or delegate for this case). So I would think that: void foo(ref void function() fn) { } The above 'foo' would receive a function pointer by reference, while: void foo(void function() ref fn) { } Would receive a function pointer which returns by ref.
It's very counter intuitive to mark the _function_ ref, rather than it's return type.
May 04 2012
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 15:49:03 UTC, Manu wrote:
 It's very counter intuitive to mark the _function_ ref, rather 
 than it's
 return type.
It is a function attribute, so it makes perfect sense. The rest is an issue of documentation/education. I agree it may not be optimally intuitive, but I don't see any superior syntactic options.
May 04 2012
next sibling parent Manu <turkeyman gmail.com> writes:
On 4 May 2012 18:55, Jakob Ovrum <jakobovrum gmail.com> wrote:

 On Friday, 4 May 2012 at 15:49:03 UTC, Manu wrote:

 It's very counter intuitive to mark the _function_ ref, rather than it's
 return type.
It is a function attribute, so it makes perfect sense. The rest is an issue of documentation/education. I agree it may not be optimally intuitive, but I don't see any superior syntactic options.
Well, I personally see no reason not to allow 'ref' variables anywhere, just like in C++. Breaking out pointers in D feels a bit dirty, by the same reasoning that you use C++ references. Why not make it a type modifier? It would just be a guaranteed initialised pointer like in C++, and with no pointer assignment semantics.
May 04 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-04 17:55, Jakob Ovrum wrote:
 On Friday, 4 May 2012 at 15:49:03 UTC, Manu wrote:
 It's very counter intuitive to mark the _function_ ref, rather than it's
 return type.
It is a function attribute, so it makes perfect sense. The rest is an issue of documentation/education. I agree it may not be optimally intuitive, but I don't see any superior syntactic options.
ref int a (); const int b (); const(int) c (); "a" is function returning an int by reference. "b" is a const function returning an int. "c" is a function returning a const int. Don't you see how it's confusing. Perhaps it would be better if "a" was declared like this: ref(int) a (); -- /Jacob Carlborg
May 04 2012
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 4 May 2012 at 20:00:10 UTC, Jacob Carlborg wrote:
 ref int a ();
 const int b ();
 const(int) c ();
I fully understand the difference, it's a common source of confusion. But it also makes perfect sense if you know the rules about function attributes. I don't think it's optimal, but changing it now would break a lot of code, it cannot happen for D2. The best we can do is make 'ref' work properly as a function attribute by allowing it to occur after the parameter list. 'inout' also has this problem, but opposite; sometimes putting it in front of the member function makes it behave differently. I can't remember if there is a bug report for it (probably is... or maybe not, because nobody even expected inout to work at all a couple of versions ago).
 Perhaps it would be better if "a" was declared like this:

 ref(int) a ();
ref is not a type qualifier, I think that would be even more confusing. It would be completely out of sync with the rest of the language.
May 04 2012
next sibling parent Manu <turkeyman gmail.com> writes:
On 4 May 2012 23:16, Jakob Ovrum <jakobovrum gmail.com> wrote:

 Perhaps it would be better if "a" was declared like this:
 ref(int) a ();
ref is not a type qualifier, I think that would be even more confusing. It would be completely out of sync with the rest of the language.
But maybe it should be, then you'd be able to declare ref variables anywhere, like in C++... what's the disadvantage of that?
May 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Saturday, May 05, 2012 02:30:00 Manu wrote:
 On 4 May 2012 23:16, Jakob Ovrum <jakobovrum gmail.com> wrote:
 Perhaps it would be better if "a" was declared like this:
 ref(int) a ();
ref is not a type qualifier, I think that would be even more confusing. It would be completely out of sync with the rest of the language.
But maybe it should be, then you'd be able to declare ref variables anywhere, like in C++... what's the disadvantage of that?
I know that Walter's against it, but unfortunately, I don't recall his arguments. But I'd certainly be very surprised if it ever happened. - Jonathan M Davis
May 04 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 5 May 2012 02:38, Jonathan M Davis <jmdavisProg gmx.com> wrote:

 On Saturday, May 05, 2012 02:30:00 Manu wrote:
 On 4 May 2012 23:16, Jakob Ovrum <jakobovrum gmail.com> wrote:
 Perhaps it would be better if "a" was declared like this:
 ref(int) a ();
ref is not a type qualifier, I think that would be even more
confusing. It
 would be completely out of sync with the rest of the language.
But maybe it should be, then you'd be able to declare ref variables anywhere, like in C++... what's the disadvantage of that?
I know that Walter's against it, but unfortunately, I don't recall his arguments. But I'd certainly be very surprised if it ever happened.
Yes, I get that impression also. But it seems strange, it would automatically solve these problems, and as a handy bonus, it would be useful in lots of other situations! :)
May 04 2012
parent reply "Remo" <remotion4d googlemail.com> writes:
Hi,

are there any news about this problem ?

This code does compile.
[code]
ref int min(ref int lhs,ref int rhs) {
	return lhs > rhs ? rhs : lhs;
}
auto fptr = &min;

pragma(msg,typeof(fptr).stringof);  //int function(ref int lhs, 
ref int rhs) ref
[/code]

But how to manually specify type of fptr?

This does not compiles
[code]
int function(ref int lhs, ref int rhs) ref  fptr3 = &min; 
//Error:  no identifier for declarator int function(ref int lhs, 
ref int rhs)
[/code]

this one too.
[code]
ref int function(ref int lhs, ref int rhs)   fptr3 = &min; 
//Error: only parameters or foreach declarations can be ref
[/code]

Right now I am using dmd.2.065.0-rc1.
Feb 19 2014
next sibling parent "Remo" <remotion4d googlemail.com> writes:
Hm [code] does not work.

Any way here is the test code.
http://melpon.org/wandbox/permlink/ZDz42rynoTaK1P4o


On Wednesday, 19 February 2014 at 16:20:39 UTC, Remo wrote:
 Hi,

 are there any news about this problem ?

 This code does compile.
 [code]
 ref int min(ref int lhs,ref int rhs) {
 	return lhs > rhs ? rhs : lhs;
 }
 auto fptr = &min;

 pragma(msg,typeof(fptr).stringof);  //int function(ref int lhs, 
 ref int rhs) ref
 [/code]

 But how to manually specify type of fptr?

 This does not compiles
 [code]
 int function(ref int lhs, ref int rhs) ref  fptr3 = &min; 
 //Error:  no identifier for declarator int function(ref int 
 lhs, ref int rhs)
 [/code]

 this one too.
 [code]
 ref int function(ref int lhs, ref int rhs)   fptr3 = &min; 
 //Error: only parameters or foreach declarations can be ref
 [/code]

 Right now I am using dmd.2.065.0-rc1.
Feb 19 2014
prev sibling next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Wednesday, 19 February 2014 at 16:20:39 UTC, Remo wrote:
 Hi,

 are there any news about this problem ?

 This code does compile.
 [code]
 ref int min(ref int lhs,ref int rhs) {
 	return lhs > rhs ? rhs : lhs;
 }
 auto fptr = &min;

 pragma(msg,typeof(fptr).stringof);  //int function(ref int lhs, 
 ref int rhs) ref
 [/code]

 But how to manually specify type of fptr?

 This does not compiles
 [code]
 int function(ref int lhs, ref int rhs) ref  fptr3 = &min; 
 //Error:  no identifier for declarator int function(ref int 
 lhs, ref int rhs)
 [/code]

 this one too.
 [code]
 ref int function(ref int lhs, ref int rhs)   fptr3 = &min; 
 //Error: only parameters or foreach declarations can be ref
 [/code]

 Right now I am using dmd.2.065.0-rc1.
Looks like it's a bug. A workaround is: typeof(&min) fprt = &min; Or just use auto like in your example above.
Feb 19 2014
parent reply "Remo" <remotion4d googlemail.com> writes:
 Looks like it's a bug.
How to report this bug ? It is not possible to use auto because in real code the functions are extern(C).
 A workaround is: typeof(&min) fprt = &min;
Yes I already found this workaround, but it is really really ugly this way. private ref int __hidden_fn_1002(ref int lhs,ref int rhs); typeof(&__hidden_fn_1002) fprt; Is there a way to make this much shorter? Something like this ? typeof(& (ref int __hidden_fn_1002(ref int lhs,ref int rhs))) fprt; On Wednesday, 19 February 2014 at 16:47:08 UTC, Meta wrote:
 On Wednesday, 19 February 2014 at 16:20:39 UTC, Remo wrote:
 Hi,

 are there any news about this problem ?

 This code does compile.
 [code]
 ref int min(ref int lhs,ref int rhs) {
 	return lhs > rhs ? rhs : lhs;
 }
 auto fptr = &min;

 pragma(msg,typeof(fptr).stringof);  //int function(ref int 
 lhs, ref int rhs) ref
 [/code]

 But how to manually specify type of fptr?

 This does not compiles
 [code]
 int function(ref int lhs, ref int rhs) ref  fptr3 = &min; 
 //Error:  no identifier for declarator int function(ref int 
 lhs, ref int rhs)
 [/code]

 this one too.
 [code]
 ref int function(ref int lhs, ref int rhs)   fptr3 = &min; 
 //Error: only parameters or foreach declarations can be ref
 [/code]

 Right now I am using dmd.2.065.0-rc1.
Looks like it's a bug. A workaround is: typeof(&min) fprt = &min; Or just use auto like in your example above.
Feb 19 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 19 February 2014 at 17:01:15 UTC, Remo wrote:
 Looks like it's a bug.
How to report this bug ? It is not possible to use auto because in real code the functions are extern(C).
Perhaps I'm missing something, but auto isn't incompatible with extern(C)
Feb 19 2014
parent "Remo" <remotion4d googlemail.com> writes:
 Perhaps I'm missing something, but auto isn't incompatible with 
 extern(C)
What I mean is that I only need to define function pointer to a function. The function it self is extern and is a C++/C function.
Feb 19 2014
prev sibling parent Jerry <jlquinn optonline.net> writes:
"Remo" <remotion4d googlemail.com> writes:

 Looks like it's a bug.
How to report this bug ?
https://d.puremagic.com/issues/
Feb 19 2014
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 02/19/14 17:20, Remo wrote:
 
 This code does compile.
 [code]
 ref int min(ref int lhs,ref int rhs) {
     return lhs > rhs ? rhs : lhs;
 }
 auto fptr = &min;
 
 pragma(msg,typeof(fptr).stringof);  //int function(ref int lhs, ref int rhs)
ref
 [/code]
 
 But how to manually specify type of fptr?
 
 This does not compiles
 [code]
 int function(ref int lhs, ref int rhs) ref  fptr3 = &min; //Error:  no
identifier for declarator int function(ref int lhs, ref int rhs)
 [/code]
 
 this one too.
 [code]
 ref int function(ref int lhs, ref int rhs)   fptr3 = &min; //Error: only
parameters or foreach declarations can be ref
 [/code]
alias extern(C) ref int function(ref int lhs, ref int rhs) Ftype; Ftype fprt; artur
Feb 19 2014
parent "Remo" <remotion4d googlemail.com> writes:
Excellent, this way is much better.

Thanks you artur.

On Wednesday, 19 February 2014 at 19:55:30 UTC, Artur Skawina 
wrote:
 On 02/19/14 17:20, Remo wrote:
 
 This code does compile.
 [code]
 ref int min(ref int lhs,ref int rhs) {
     return lhs > rhs ? rhs : lhs;
 }
 auto fptr = &min;
 
 pragma(msg,typeof(fptr).stringof);  //int function(ref int 
 lhs, ref int rhs) ref
 [/code]
 
 But how to manually specify type of fptr?
 
 This does not compiles
 [code]
 int function(ref int lhs, ref int rhs) ref  fptr3 = &min; 
 //Error:  no identifier for declarator int function(ref int 
 lhs, ref int rhs)
 [/code]
 
 this one too.
 [code]
 ref int function(ref int lhs, ref int rhs)   fptr3 = &min; 
 //Error: only parameters or foreach declarations can be ref
 [/code]
alias extern(C) ref int function(ref int lhs, ref int rhs) Ftype; Ftype fprt; artur
Feb 19 2014