The Status of Const

Michel Fortin michel.fortin at michelf.com
Mon Aug 16 09:28:29 PDT 2010


On 2010-08-16 11:39:15 -0400, "Steven Schveighoffer" 
<schveiguy at yahoo.com> said:

> Translating it to your example, should you be able to convert from a  
> const(SmartPointer!X) to a SmartPointer!(const X) ?  I'd say no, 
> because  const(SmartPointer!X) guarantees that the refCount will not 
> change.

Indeed, you can't convert const(SmartPointer!X) to SmartPointer!(const 
X). Doing that is what I'd call logical-const, and it'd be contrary to 
the const system in D.


> Implicit casting to your version of tail-const breaks that guarantee.

I only suggested casting the other way around: SmartPointer!(X) to 
SmartPointer!(const X). You're implying things I didn't meant because 
your definition of tail-const is different than mine.


> One  of the *essential* properties of tail const is you should always 
> be able  to implicitly convert a const(T) to a tail const(T).

Then, by *your* definition of tail const, the SmartPointer cannot be 
tail-const. *My* definition of tail-const just means that the tail is 
const and the head is not, irrespective of what conversions are allowed.

So I think we agree except on the correct definition for tail-const. I 
think mine is simpler and more to the point, but that's just my opinion.


>> Wouldn't defining ranges like the above fix the problem? And you could  
>> make ranges cast implicitly to their "tail-const" form when needed,  
>> exactly like the smart pointer above.
> 
> It might make it possible, but it would be a mess.  A range would be a  
> templated type inside the templated container type.  Or you could 
> define a  range outside the container type to avoid odd issues.

The important things is to have the constness of the container "known" 
by the range type, so all you need is two separate ranges types 
(template arguments create separate types). The STL uses iterator and 
const_iterator, that'd work too. Which brings me to...

> But implicit  casting is going to be difficult. You also have to 
> contend with stuff  like this:
> 
> struct Range(V)
> {
>     static if(isConst!(V)) // not sure if this exists, but assume it does
>     {
>        bool makeUncastable;
>     }
>     V *cur;
> }
> 
> So a Range!(const(V)) cannot be implicitly converted to Range!V because 
>  the layout is different.  I'd rather not rely on templates and  
> compile-time decisions, and just let the compiler enforce the simple 
> cases.

For complicated cases like the one above, wouldn't a layout such as 
this one work?

	struct ConstRange(V) {
		...
	}

	struct Range(V) {
		ConstRange _constRange;
		alias _constRange this;

		...
	}

We're reinventing static-inheritance using "alias this". :-) Of course, 
I'm assuming implicit conversion from Range to ConstRange will work 
somehow; this still need to be fixed.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list