DIP 1014
Stanislav Blinov
stanislav.blinov at gmail.com
Wed Oct 3 13:56:29 UTC 2018
Shachar, as I don't see a better place of discussing that DIP at
the moment, I'll pour some observations and thoughts in here if
you don't mind, will add some comments on GitHub later.
As I see it right now, it's a case of over-engineering of a quite
simple concept.
1. A new function, called __move_post_blt, will be added to
DRuntime.
That's unnecessary, if not downright harmful for the language. We
should strive to remove things from DRuntime, not add to it. The
core language should deal with type memory, not a .so or dll. And
it's extraneous, because...
2 and 3. onPostMove and __move_post_blt:
They're unnecessary as well. All that's required is to allow a
by-value constructor, e.g:
struct S {
this(S rhs);
}
Any function in D that has a signature of the form
ReturnType foo(Type x);
in C++ would have an equivalent signature of
ReturnType foo(Type&& x); // NOT ReturnType foo(Type x);
because passing by value in D always implies a possible move. The
'x' in such functions can be safely cannibalized without any
repercussions, as it is either a temporary on the call site, or,
which is especially pertaining to the original bugzilla
discussion, constructed in place via copy elision.
Thus in effect this(S) would be an equivalent of C++'s move
constructor. We already have a de-facto move-assignment in the
form of opAssign(S), this(S) would be a natural extension to that.
Note, per above, that it is NOT a copy constructor, although user
code may want to create a copy *before* calling it, to create the
temporary.
Such approach reduces added complexity. The only potential
problem with it would be a need to "special-case" initialization
from .init, although at the moment, I think even that may be
unnecessary: this is a hook after all.
Your example from the DIP would become:
struct Tracker {
static uint globalCounter;
uint localCounter;
uint* counter;
@disable this(this);
this(bool local) {
localCounter = 0;
if( local )
counter = &localCounter;
else
counter = &globalCounter;
}
this(Tracker oldLocation) {
if( counter is &oldLocation.localCounter )
counter = &localCounter;
}
void increment() {
(*counter)++;
}
}
Usage:
auto old = Tracker(true);
// ...
auto new = move(old); // calls Tracker.this(Tracker);
...this avoids any need to inject special postblits into user
code.
As I see it, in addition to the above, what would be really
desirable is for move() and emplace() family of calls to become
compiler intrinsics instead of library constructs. Those at the
moment are complete poison: being templates they infect user code
with dependencies on libc (moveEmplace calls memset and memcpy of
all things) and unnecessary calls to DRuntime (typeid), and they
of course blow up the amount of generated code in the form of
template instantiations. That's despite the fact that the
compiler possesses ALL the necessary knowledge at the time of
those calls.
More information about the Digitalmars-d
mailing list