On Tuesday, 16 October 2018 at 02:26:04 UTC, Manu wrote:
I understand your point but I think the current shared (no implicit conversion) has its uses. It can be quite useful to have one interface for when an object is shared and one for when it is not (one with and without the synchronization cost). Sure, something as trivial as a counter can be re-implemented in both ways but more complex objects would easily result in extreme code duplication.

If you can give a single 'use', I'm all ears ;)

My usages are a custom ref counted template and list types (which are built on top of the former). The ref counted template will initialize naively when not shared but utilize compare-and-set and thread yielding if needed when shared (ensureInitialized can occur any time after declaration). The list types (which are not shared-compatible *yet*) will utilize a read-write mutex only when shared (no cost beyond a little unused memory to non-shared objects). As such, casting any of the non-shared versions of these types to shared would be unsafe.

(Technically the types can be safely casted to shared so long as no non-shared
reference to them exists and vice versa.)

It's also easy to acknowledge that implicit conversion to shared has its uses.
I actually know of many real uses for this case.
(There was a time when I wanted it as well. I've forgotten what for by now.)

That might be fine.
Like I said in OP, the first point that I think needs to be agreed on,
is that shared can not read or write members. I think that's a
pre-requisite for any interesting development.

I will agree that *outsiders* should not be able to read/write members of a shared object. I'm not sure whether your design means even within a shared function such members cannot be read from or written to. If it does, the casting required may get a little annoying but isn't unworkable (especially since an unshared template can do the cast in an @trusted manner).

Reply via email to