How to rewrite C ++ code that uses mutable in D?

If you need to rewrite the following C ++ code into D, how would you do it?

struct A{ const S* _s; B _b; C _c; mutable C _c1, _c2; A(const B& b, const C& c, const S* s){ /*...*/ } void compute(const R& r) const { //... _c1 = ... _c2 = ... } }; 

D is not mutable , and based on my experience, it is rarely used in C ++. But assuming mutable used for the right reasons, what are my options in D?

+6
source share
3 answers

You have three options:

  • Drop const . This will delay the compiler, but there is no guarantee that your code will work as intended. In particular, if you call this function on the same object from several threads, then you are at the mercy of data calculations.

  • 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!

+3
source

D immutable transitive if an immutable reference is given (for example, the this reference in an immutable member function), all fields are also immutable. There is no way around this in D. const only in D to bind mutable and immutable data, but since immutable is implicitly converted to const, it must also be transitive. When you go unchanged (or const), you cannot go back.

The benefits are as follows: immutable data can be shared between threads safely, can be placed in ROM, if desired, and easy to reason.

There is simply no room for a logical const in D, better or worse.

+6
source

Short version you cannot, by design.

A longer version, the D designers concluded (after some epic debate) that the advantages of mutable are outweighed by the cons. (See: JA_cOp for an answer to some of the details, many of the other reans are driven by the intention to do parallel programming, and the argument is less ugly there.)

+4
source

Source: https://habr.com/ru/post/904728/


All Articles