Use an external data structure to store mutable objects:
struct A { static C[const(A)*] _c1s, _c2s; void compute(ref const(R) r) const { _c1s[&this] = ... _c2s[&this] = ... } }
I use &this as the key to an external hash table, but you probably would be better off using some sort of unique identifier. This is a very ugly and complicated solution. I do not like it. Also note that hash tables are thread-local, so the same object will have different values ββfor different streams. This may or may not be desirable for your specific application.
Rethink how you use const in D.
In D, const is transitive and bitwise, i.e. boolean const is not supported. The purpose of this is to guarantee simultaneous joint recording of data. Despite the fact that your code may be logically correct, it will still break if two threads try to call compute on the same object, so D does not allow it and does not give a legal exit (no mutable ).
Essentially, you should mark functions as const only when they are bitwise const.
As a result, you should use const much less in D than in C ++, because you need a bitwise const much less than you need a logical constant.
As an example, consider a simple (meaningless) common function equal , which tells you whether two objects are equal:
bool equal(T)(T lhs, T rhs) { return lhs == rhs; }
Note that function parameters were not marked as const . This is special. Testing for equality should not require a bitwise const - it only requires a logical constant, so the forced level D const on objects will be uselessly restrictive.
As jA_cOp says, the D community sees no place for a logical const in D, better or worse. The problem arises when you try to use D const as C ++ const. They are not the same, so do not use them the same way! If at all there is any possibility that the function may require the use of a logical const, then do not mark them as bitwise const!