On Wednesday, 30 May 2018 at 21:02:07 UTC, Jonathan M Davis wrote:
On Wednesday, May 30, 2018 20:42:38 Q. Schroll via
Digitalmars-d-learn wrote:
It seems one cannot std.algorithm.mutation.move objects
explicitly. Say I have a non-copyable type
[...]
It fails because move() cannot be executed at compile time. The
reason
"memcpy cannot be interpreted at compile time, because it
has
no available source code"
sounds very suspicious.
Why is it suspicious? memcpy is a C function, and you can't
call C functions during CTFE precisely because the compiler
doesn't have their source code. You can't call D functions
either if the compiler doesn't have their source (e.g. if
you're using a .di file to hide the implementation).
I definitely do understand the error message and it makes sense
that it fails the way it's implemented. However, it makes no
sense that moving as a concept can fail at CTFE. That's what I
find suspicious. [Maybe 'suspicious' isn't the right term; I
couldn't express it better.] You can move rvalues at CTFE which
proves that the compiler can do it.
Shouldn't it be possible to move at CTFE,
too, or does it mean, non-copyable types are practically
unusable
for CTFE?
You can't do much in the way of pointer or memory manipulation
during CTFE (e.g. no pointer arithmetic or reinterpret casts).
So, I don't see how a move could be done during CTFE. Even if
the source for memcpy were available during CTFE, I suspect
that it wouldn't be allowed due to the lower level stuff that
it does.
That's the explanation why probably all currently possible
library alternatives to memcpy would fail. I suspected that when
encountering the error, but still wonder why memcpy or other
low-level stuff is even necessary to accomplish something the
compiler is perfectly able to do.
From what I see, the reason for the hack is lack of
expressiveness: We don't have rvalue-refs in D (which I find
good) so, currently, there is no cast-solution as in C++. So for
a proper move() that works at CTFE, we'd need some specific tool.
I have no idea of the details on how the compiler handles
lvalues. Would it make sense to add a compiler trait,
specifically to solve moving? Like __traits(move,
lvalue_expression) [name up for discussion] that is identical to
lvalue_expression with the exception that the (lvalue/rvalue)
flag (or whatever it is) is set to "rvalue". Basically, it's the
C++ solution: After the "cast", the compiler will proceed and
pretend it is an rvalue and therefore initiate moving.
Do you think adding a trait to make move() and swap() work at
CTFE is worth it?
A quick search showed me the class "Expression" has "virtual bool
isLvalue();" so it might be easy as wrapping and hooking that
virtual method. To me, [1] highly suggests that it works.
[1]
https://github.com/dlang/dmd/blob/master/src/dmd/expression.d#L1219