www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - determine parameter storage class in D 2.0

reply Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
Has someone figured out a reliable way to determine at compile time whether
a function parameter is passed by reference or by copy?

The functionality (ParamsPassMethodTuple) in std.bind does not work. (It
expects that giving a const T to a function expecting ref T will fail,
which leads to wrong results for simple types like int.) 

Modifying it to check with enum T, invariant T or the type's initializer
fails. I noticed that ParameterTypeTuple!(function) contains the ref/out
etc. in the tuple, but there seems to be no way to test for it. (stringof
aside)

Anyway, I think it's odd that for

void foo(ref int i) {}
void foo2(ParameterTypeTuple!(foo)) {}

ParameterTypeTuple!(foo) is (ref int) and
ParameterTypeTuple!(foo2) is (int).

Regards,
Christian Kamm
Feb 03 2008
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Christian Kamm wrote:
 Has someone figured out a reliable way to determine at compile time whether
 a function parameter is passed by reference or by copy?
 
 The functionality (ParamsPassMethodTuple) in std.bind does not work. (It
 expects that giving a const T to a function expecting ref T will fail,
 which leads to wrong results for simple types like int.) 
 
 Modifying it to check with enum T, invariant T or the type's initializer
 fails. I noticed that ParameterTypeTuple!(function) contains the ref/out
 etc. in the tuple, but there seems to be no way to test for it. (stringof
 aside)
 
 Anyway, I think it's odd that for
 
 void foo(ref int i) {}
 void foo2(ParameterTypeTuple!(foo)) {}
 
 ParameterTypeTuple!(foo) is (ref int) and
 ParameterTypeTuple!(foo2) is (int).
 
 Regards,
 Christian Kamm
Looks like a bug
Feb 03 2008
parent Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
 Christian Kamm wrote:
 Anyway, I think it's odd that for
 
 void foo(ref int i) {}
 void foo2(ParameterTypeTuple!(foo)) {}
 
 ParameterTypeTuple!(foo) is (ref int) and
 ParameterTypeTuple!(foo2) is (int).
Robert Fraser wrote:
 Looks like a bug
I'm not sure. After all it is a type tuple - and ref int isn't a distinct type from int. Also void foo(ref int i) {} ParameterTypeTuple!(foo).stringof == "(ref int)" ParameterTypeTuple!(foo)[0].stringof == "int". A while back Andrei found it problematic that there is no way to write a function template ident(F) such that foo and ident!(foo) behave exactly the same. It might be the beginnings of a not-yet-done storage class manipulation feature.
Feb 03 2008
prev sibling parent Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
For the record, this works for me:

template isRefArg(int i, alias func)
{
    enum isRefArg = 
        ParameterTypeTuple!(func)[i..i+1].stringof == 
        ParameterTypeTuple!(
            void delegate(ref ParameterTypeTuple!(func)[i])
          ).stringof;
}

Note that the [i..i+1] leads to the storage class being retained where [i]
would discard it.

I have reported some of the behavior as bug 1818:
http://d.puremagic.com/issues/show_bug.cgi?id=1818 .

Cheers,
Christian
Feb 05 2008