Request: a more logical static array behavior
Tommi
tommitissari at hotmail.com
Wed Aug 14 17:57:25 PDT 2013
Disclaimer: I'm going to be excruciatingly explicit here just so
that everybody can follow my train of thought.
References:
1) Subtype/Supertype: http://en.wikipedia.org/wiki/Subtyping
2) Type deduction:
http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-2-of-n
3) Range: http://dlang.org/phobos/std_range.html#isInputRange
-------
e.g. = "for example"
Static array, e.g. int[3], is not a range.
Dynamic array, e.g. int[], is a range.
int[] is not a supertype of int[3].
Non-subtype type: "type that is not a subtype of any other type"
Static array types are somewhat magical in D; they can do
something that no other non-subtype type can do: static arrays
can implicitly convert to another type during type deduction.
More specifically, e.g. int[3] can implicitly convert to int[]
during type deduction.
Here's an example of this:
module test;
enum Ret { static_array, dynamic_array, input_range }
Ret foo(T)(T[3] sa) // [1]
if (is(T == uint))
{
return Ret.static_array;
}
Ret foo(T)(T[] da) // [2]
{
return Ret.dynamic_array;
}
enum uint[3] saUints = [0, 0, 0];
enum char[3] saChars = [0, 0, 0];
static assert(foo(saUints) == Ret.static_array); // [3]
static assert(foo(saChars) == Ret.dynamic_array); // [4]
-------
[3]: A perfect match is found in the first overload of 'foo' [1]
when its template type parameter 'T' is deduced to be an int.
Then, the type of the function parameter 'sa' is exactly the same
as the type of the argument 'saUints'.
[4]: No perfect match is found. But, because 'saChars' is a
static array, the compiler gives all 'foo' overloads the benefit
of the doubt, and also checks if a perfect match could be found
if 'saChars' were first converted to a dynamic array, int[] that
is. Then, a perfect match is found for int[] in the second
overload of 'foo' [2] when 'T' is deduced to be an int.
Now, let's add to the previous example:
import std.range;
Ret bar(T)(T[3] sa) // [5]
if (is(T == uint))
{
return Ret.static_array;
}
Ret bar(R)(R r) // [6]
if (std.range.isInputRange!R)
{
return Ret.input_range;
}
static assert(bar(saUints) == Ret.static_array); // [7]
static assert(bar(saChars) == Ret.input_range); // [8]
-------
[7]: This is effectively the same as [3]
[8]: This line throws a compile-time error: "template test.bar
does not match any function template declaration". Compare this
to [4]: for some reason, the compiler doesn't give the second
overload of 'bar' [6] the benefit of the doubt and check to see
if the call to 'bar' could be made if 'saChars' were first
converted to int[]. Were the compiler to consider this implicit
conversion as it does in [4], then it would see that the second
overload of 'bar' [6] could in fact be called, and the code would
compile.
Thus, my point is this:
Shouldn't this magical property of static arrays (implicitly
converting to dynamic array during type deduction) extend to all
type deduction situations?
I think this would be a breaking change.
NOTE:
Subtypes can implicitly convert to their supertype during type
deduction, there's nothing magical about that.
More information about the Digitalmars-d
mailing list