Tagging of arguments ref/out, or just out

Timon Gehr timon.gehr at gmx.ch
Mon Aug 8 07:05:26 PDT 2011


Michel Fortin wrote:
> On 2011-08-07 20:42:30 +0000, bearophile <bearophileHUGS at lycos.com> said:
>
>> This is a recently opened (not by me) enhancement request thread:
>> http://d.puremagic.com/issues/show_bug.cgi?id=6442
>>
>> It proposes something that I remember was discussed and refused two
>> times in past: to require (but only optionally!) "ref" and "out" at the
>> calling point, as C#4 instead always requires (optionally for COM):
>>
>>     void foo(ref int bar) { ... }
>>     int i = 0;
>>     foo(ref i);   // <------- here
>>
>>     void foo(out int bar) { ... }
>>     int i = 0;
>>     foo(out i);   // <------- here
>>
>>
>> Jonathan M Davis has then argued that they clutter the code, and that
>> making them optional makes them kind of useless. See the thread for
>> more details.
>>
>> -----------------
>>
>> After thinking some about it, I have suggested a related but
>> alternative proposal: to ask only for the "out" at the calling point,
>> make it obligatory if you compile with -warning and optional otherwise
>> (for a long time "override" was like this). I think having "out" at the
>> calling point is more useful than "ref".
>>
>> […]
>
> I don't find your arguments very enticing, sorry. But I do see *one*
> solid reason we might want to add 'ref' and 'out', optional or not, at
> the call site: variadic templates.
>
> I recently had to use getopt. You use it like that:
>
>  bool option;
>  int counter;
>
>  getopt(args,
>   "option|o", &option,
>   "counter|c", &counter);
>
> The problem is that taking addresses of a stack variable is disabled in
> SafeD, which means getopt doesn't work in SafeD, which puts SafeD in a
> strange position.
>
> It'd work if we used 'ref' parameters. The problem is that getopt is
> defined like this:
>
>  void getopt(T...)(ref string[] args, T opts);
>
> Using a type tuple makes it impossible to have 'ref's where they need
> to be, hence the use of pointers.
>
> Type tuples could be made support propagating the type including the
> 'ref' or 'out' storage class applied on them, which would allow you to
> write this:
>
>  getopt!(string, ref bool, string, ref int)(args,
>   "option|o", option,
>   "counter|c", counter);
>
> But that doesn't work with type deduction. It could work however if you
> allowed specifying the 'ref' as part of the argument list:
>
>  getopt(args,
>   "option|o", ref option,
>   "counter|c", ref counter);
>
> I'd prefer if we had a solution that doesn't require you to write 'ref'
> at the call site, but I haven't found any. Ideas?
>
>
> --
> Michel Fortin
> michel.fortin at michelf.com
> http://michelf.com/


void getopt(T...)(ref string[] args, ref T opts);

Would work afaik (but all the flag names would be passed by ref too).
std.stdio.readf has the same issue.

The general problem is that type deduction does not currently work too well with
implicit conversions (that is also the reason why most string algorithms in Phobos
don't work with immutable strings)

I can see a possible solution to the problem: At definition side, it should be
possible to manually influence type and storage class deduction.

But I cannot think of syntax for this that wouldn't look awkward. Any ideas?



More information about the Digitalmars-d mailing list