Const template

Walter Bright newshound at digitalmars.com
Sun Jan 21 21:01:34 PST 2007


Andrei Alexandrescu (See Website For Email) wrote:
> Today, Walter and myself have come with a semantics for const (as in, 
> "read-only view" that) seems to be a good starting point.

Five hours of coffee and scribbling <g>. Neither of us is thoroughly 
happy with the result, but at least we do have that good starting point.

> * const is not removable legally via a cast. But the compiler must 
> assume in the general case that a const view may alias with a modifiable 
> view. This is a weak point of the design. The hope is that in most cases 
> the compiler will easily prove non-aliasing and can do a good job at 
> optimizing based on const. Example: all pure functions don't care about 
> aliasing to start with.

An important clarification on that: the compiler *can* assume that the 
'shallow const' portion (defined below) will not change. There's no way 
the compiler can guarantee it won't change (for various technical 
reasons), so it will be up to the user to ensure that no other thread or 
alias changes it for the duration of the scope. I'll also argue that the 
C++ requirement that the compiler assume it will change offers no usable 
advantage, it just sabotages optimizations.

> * Shallow const is achievable via final. Final only means a value is not 
> supposed to be changed, but anything reachable through it can be mutated.
> 
> * The syntax for manually-annotated const is:
> 
> struct Widget
> {
>   void Foo(const)(int i) { ... }
> }

In C++ this is analogous to:

struct Widget
{
   void Foo(int i) const { ... }
}

I never liked the C++ syntax for attributing the 'this' pointer.

> 
> This is in the spirit of current D, because Foo can be seen as a 
> specialization for a subset of Widget types.
> 
> * If you do want to make Foo a template, it's:
> 
> struct Widget
> {
>   void Foo(const, T)(T i) { ... }
> }
> 
> * D avoids the issue of duplicated function bodies in the following way:
> 
> struct Widget
> {
>   storageof(this) int* Foo(storageof(this))(int i) { ... }
> }
> 
> This code transports whatever storage 'this' has to the result type. 
> More involved type computations are allowed because inside Foo, 
> typeof(this) includes the storage class. Effectively Foo above is a 
> template.
> 
> * Constructors and destructors can figure the storage class of the 
> object being constructed. This is useful for selecting different 
> allocation strategies for immutable vs. mutable objects:
> 
> class Widget
> {
>   this(int i) { ... }
>   this(const)(int i) { ... }
>   ~this() { ... }
>   ~this(const)() { ... }
> }
> 
> Const cdtors can obviously mutate the object being cdted. In a cdtor, 
> 'const' is not enforced -- it's just an information for the programmer.
> 
> * Walter sustains that given the above, there will never be a need to 
> overload member functions based on const. I disagree, but I couldn't 
> come up with a salient example. Besides, I don't care that much because 
> the semantics above do allow telling const from nonconst, just in a 
> roundabout way.



More information about the Digitalmars-d mailing list