digitalmars.D.learn - Casting lvalues
```d shared TT[] a; T processArray(T)(ref T[] p){/*...*/} //function calls .reserve on its parameter a.processArray; ```Template *name* cannot deduce function from argument types !()(shared(T[]))...Even if the function is changed to only accept shared parameters, .reserve does not appear to support shared so the function is impossible to use without somehow changing its type or using __gshared. Other than using pointers and casting(```processArray(*(cast(Unqual!TT*)&a))```, not ideal), is there a better way to transform an lvalue's type without it transforming into an rvalue?(direct casting seems to create an rvalue because compilation fails.) Thanks
Apr 02 2021
On Friday, 2 April 2021 at 12:47:35 UTC, z wrote:```d T processArray(T)(ref T[] p){/*...*/} //function calls .reserve ```i meant `void` for the function return type.
Apr 02 2021
On Friday, 2 April 2021 at 12:47:35 UTC, z wrote:Even if the function is changed to only accept `shared` parameters, `.reserve` does not appear to support `shared` so the function is impossible to use without somehow changing its type or using `__gshared`.There is no way that `.reserve` can correctly support `shared`, because it cannot know how to correctly synchronize the slice and its contents in the larger context of the whole program. In general, just casting away `shared` to make the compiler stop complaining completely defeats the purpose of `shared`, and makes it just as unsafe as `__gshared`. Instead, you must do any necessary synchronization yourself using, for example, `core.sync.mutex`. Only within properly synchronized regions should you cast away `shared`. This is the purpose of `shared`, and the only difference from `__gshared`: to remind you to synchronize by requiring the use of a cast to do much of anything. Typically, you should synchronize an entire region of code across which the `shared` data under protection will begin and end with all invariants satisfied. Synchronizing individual operations (like just `.reserve` by itself) is usually wrong - or rather, insufficient. The synchronization must guarantee that whenever a thread is writing to the data, it has exclusive access. But, it is safe and fast to have multiple threads read data simultaneously, as long as it is not written to during that time. `core.sync.rwmutex` can be used to implement this optimization. (It is possible to design algorithms that support multiple simultaneous writers using lock-free algorithms (see `core.atomic`) or other more complicated schemes, but this is much harder to do correctly and usually not necessary.) Finally, if you only need to write the data once, after which it will only be read, then you can skip all of this confusion and complexity by just preparing the data from a single thread in a non-`shared` container and then using `cast(immutable)` (if there is only one extant reference to the data) or `.idup` (otherwise). No synchronization is necessary for `immutable` data.`*(cast(Unqual!TT*)&a)`, not idealThat is the correct way to perform an lvalue reinterpret cast (provided that the resulting type is actually compatible with the source type).(direct casting seems to create an rvalue because compilation fails.)Yes, direct casting should result in an rvalue. (Although, I think it is possible to subvert this with a custom `opCast`.)
Apr 02 2021