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