IFTI, value types, and top-level const
Peter Alexander
peter.alexander.au at gmail.com
Sun Jun 9 03:33:39 PDT 2013
On Saturday, 8 June 2013 at 02:18:06 UTC, Jonathan M Davis wrote:
> On Friday, June 07, 2013 18:43:11 Peter Alexander wrote:
>> Ack, it appears it is only done for arrays and pointers :-S
>
> And it pretty much only does that because of all of the issues
> that const and
> immutable strings were giving us with range-based functions.
> IFTI now
> automatically slices arrays, and slices are now tail-const.
>
> Now, we certainly can't strip const in the general case, but
> I'm inclined to
> agree that when the mutable version of the type has no mutable
> indirections,
> stripping const would make sense. However, one problem that I
> can think of is
> that if you're dealing with an rvalue and you don't strip the
> const, under
> some circumstances, you can move the object and avoid a copy
> altogether, but
> if you strip the const, you can't do that or you'd violate the
> constness of
> the object (though maybe you could still get away with it if
> the type had no
> postblit) - and that's problem that doesn't exist in C++, since
> C++ would
> always do the copy. So, I don't know if we can quite get away
> with stripping
> const even if the type has no mutable indirections. It's
> certainly something
> that we should consider though.
It looks like the core issue here is that it's simply not
possible to create a mutable copy of a const object with
indirection:
struct S { int* p; }
const(S) a;
S b = a;
That's fair, because the current way of copying the object (via
memcpy+postblit) could lead to type system violations.
I believe this is a hole in the language. It means that it's
impossible to create slices or pointer-like types in a library
since they require this compiler magic to strip the top-level
const. This is just because of how struct copy with postblit
works, it's certainly possible and type safe in theory with some
sort of copy constructor:
struct S
{
int* p;
this(const(S) s) { p = new int; *p = *s.p; }
}
const(S) a;
S b = S(a);
And a templated slice-like type could be made with tail-const
semantics.
struct Slice(T)
{
T* ptr;
size_t length;
static if (is(T==const))
{
this(const Slice!T s) { ptr = s.ptr; length = s.length; }
this(const Slice!(Unqual!T) s) { ptr = s.ptr; length =
s.length; }
}
}
The question is, can a copy constructor be introduced into the
language without breaking lots of code, and preserving D's
approach to move operations, i.e. not requiring explicit C++
style rvalue references. I'm not sure.
More information about the Digitalmars-d
mailing list