digitalmars.D.bugs - [Issue 12672] New: make "ref" a better match than "auto_ref"
- via Digitalmars-d-bugs (72/72) Apr 28 2014 https://issues.dlang.org/show_bug.cgi?id=12672
https://issues.dlang.org/show_bug.cgi?id=12672 Issue ID: 12672 Summary: make "ref" a better match than "auto_ref" (especially for variadic arguments) Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: enhancement Priority: P1 Component: DMD Assignee: nobody puremagic.com Reporter: monarchdodra gmail.com Whenever you use "auto ref", the compiler will *completely* create different functions depending on the ref-ness of the parameters. This is necessary, since the compiler can use exploit the pass by value/pass by ref to potentially move things around without postblit. It also allows explicit things such as what is in Tuple: void opAssign(R)(auto ref R rhs) { static if (!__traits(isRef, rhs)) // Use swap-and-destroy to optimize rvalue assignment swap!(Tuple!Types)(this, rhs); else // Do not swap; opAssign should be called on the fields. field[] = rhs.field[]; } Having two template instances is fine for trivial functions, but for long functions that actually *do* things, it is better to use an "ref"/"value" overload. EG: void foo(Arg)(Arg arg) { foo(arg); } void foo(Arg)(ref Arg arg) { //longContent } This is *particularly* relevant for functions that take variadic arguments, since the compiler could potentially generate "up to" 2^^N templates, that all do the same thing (!) The issue is that when one does: void foo(Args...)(Args args) { foo(args); } void foo(Args...)(ref Args args) { //longContent } The issue with this approach though is that if *1* of the passed arguments is not a reference, the they will *all* be passed by value (postblit and all), which is quite wasteful. As such, I'd want something like: void foo(Args...)(auto ref Args args) {foo(args);} void foo(Args...)(ref Args args) {...} Unfortunately, this doesn't work, since the compiler considers these to be equal matches. The workaround is: //---- enum isRef(alias arg) = __traits(isRef, arg); auto foo(Args...)(auto ref Args args) if (!allSatisfy!(isRef, args)) { ... } auto foo(Args...)(ref Args args) { ... } //---- But this is rather ugly and unpleasant. I think the compiler should notice that there is an overload that takes only references, and as such, is a "better match" than the auto-ref version. --
Apr 28 2014