On Thursday, 24 January 2013 at 20:06:34 UTC, Ali Çehreli wrote:
On 01/24/2013 11:33 AM, Jonathan M Davis wrote:
It's intended. constness matters more than refness when
selecting a function overload. From the docs (
http://dlang.org/function.html#<u>function</u>-overloading ):
-----
Functions are overloaded based on how well the arguments to a
function can match up with the parameters. The function with
the best match is selected. The levels of matching are:
>
no match
match with implicit conversions
match with conversion to const
exact match
-----
That doesn't explain why the first case selects the ref
function:
void foo(A a) {
writeln("without ref");
foo(a); // <-- why is this foo(ref A)?
}
Because your local variable (in the signature) becomes a lvalue
and thereby reference-able.
void foo(ref A a) {
writeln("with ref");
}
foo(A) is the exact match there because the type of a is A.
What is also considered in function selection is the
rvalue-lvalue distinction, which shouldn't affect the outcome
here either.
In case David's explanation was too confusing, then let's look
at it. If your variable is non-const, it will always select a
non-const matching one first. If there is no matching non-const,
it converts it to const, then tries again.
void foo(A a) {
writeln("without ref");
//a is an lvalue but not const
//Foo(A) matches closer. Infinite loop
foo(a);
}
void foo(const ref A a) {
writeln("with ref");
}
void foo2(A a) {
writeln("foo2 - without ref");
//const lvalue, foo(const ref A) is closer
foo(cast(const A) a)
//rvalue, postblit call foo(A) (if it can)
foo(cast(const A) A());
}
I know this very issue seems like a big annoyance, to me too.
I'd say the order of preference should be const ref, const
non-ref, ref, non-ref. But then you can't have const & non const
versions unless the signature differs, like ref, more input
variables or the function itself is const.
Until/unless that is changed all 4 versions need to be written
(as David said) to make the proper calls.