Logical const

Michel Fortin michel.fortin at michelf.com
Sat Nov 20 09:43:37 PST 2010


On 2010-11-20 09:21:04 -0500, Peter Alexander 
<peter.alexander.au at gmail.com> said:

> D does not support logical const due to the weak guarantees that it provides.
> 
> So, without logical const, how are D users supposed to provide lazy 
> evaluation and memoization in their interfaces, given that the 
> interface should *seem* const, e.g.
> 
> class Matrix
> {
>    double getDeterminant() const { /* expensive calculation */ }
> }
> 
> If it turns out that getDeterminant is called often with the raw matrix 
> data remaining unchanged, how can we add caching to this class without 
> rewriting the const-ness of all code that touches it?

Using a static associative array as a cache will work:

	class Matrix
	{
		double getDeterminant() const
		{
			static double[const(Matrix)] cache;
			if (auto resultptr = (this in cache))
				return *resultptr;

			auto result = /* expensive calculation */;
			cache[this] = result;
			return result;
		}
	}

and it'll continue to work even if you pass an immutable Matrix to 
different threads (each thread has its own cache). If you don't pass 
immutable Matrixes across threads, then you don't gain anything by 
making the function const.

The main reason D has const is to facilitate the usage of immutable. If 
you don't use immutable for a given type you generally shouldn't bother 
with const either.

But in any case, you always can cast away const if you really need to, 
just be sure of what you're doing. For instance, doing this breaks 
thread-safety for immutable Matrixes:

	auto mutableThis = cast(Matrix)this;
	mutableThis.cachedDeterminant = /* expensive calculation */;


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



More information about the Digitalmars-d mailing list