On Fri, 03 Dec 2010 20:40:23 -0500, Michel Fortin
<[email protected]> wrote:
A fine explanation. Thank you.
I disagree about your proposed solution, but I recognize the problem.
The basic problem with your solution is that it creates a new kind of
const, a new kind of immutable and a new kind of shared. You should
realize that for the compiler to know the constness of member variables
inside a function, it'll have to know whether the 'this' pointer is
'const' or 'tail const'. So I think it's the wrong path.
Yes, Andrei also pointed out this problem. Part of the issue is that
member functions are always passed 'this' by ref. Arrays don't have this
problem because you have control over passing them by ref or by value. I
agree my solution does not work, or actually that it works but makes
things worse :)
The right path would be, I think, to parametrize the constness in the
type. A way to do this within the current constrains of the language
would be to make Range implicitly convertible to ConstRange, something
you should be able to do with "alias X this", X being a function
returning a ConstRange. The disadvantages are the duplication of the
opSlice function, and the inability to cast implicitly a ref Range to
ref ConstRange or a Range[] to a ConstRange[].
In fact, I'm not sure you could do Range[] to ConstRange[], I think that's
two levels of indirection.
I can sort of live with defining multiple functions, at least it would be
possible to make something work.
If we could have some way to hook inout, like designate Range for mutable,
ConstRange for const, and ImmutableRange for immutable, and let InoutRange
represent the inout type (which gets implicitly converted to one of those )
But maybe I'm dreaming :)
I have an idea that would fix those: make a template struct/class
instance implicitly convertible to another instance of that same
template if all members share the same memory layout and each member is
implicitly convertible to the same member of the other template.
I had thought of that too, a long time ago, but I wasn't sure if it could
work. I'd go two steps further:
1. all the member variable names must be identical.
2. you need to identify that implicit conversion is allowed.
1 is for sanity ;)
struct Pair(T)
{
T x;
T y;
}
struct ConstPair(T)
{
const(T) y;
const(T) x;
}
2 is to ensure you are not able to incorrectly morph data into things it
should not be. i.e.:
struct Point
{
int x;
int y;
}
I don't think you should be able to implicitly cast Pair!int to Point,
sometimes you want to define different APIs for the same data.
-Steve