digitalmars.D - Cannot use auto ref passing in expression template operator overloads
- =?UTF-8?B?Tm9yZGzDtnc=?= (67/67) Jan 18 2017 I'm currently writing a high-level GMP-wrapper at
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/4) Jan 18 2017 Should be
- Eugene Wissner (2/3) Jan 18 2017 I had the same problem with opSliceAssign, opIndexAssign lately.
I'm currently writing a high-level GMP-wrapper at https://github.com/nordlow/gmp-d In order to get efficient scheduling of calls to C API __gmpz-functions, I want expressions such as MpZ(3) + MpZ(4) to return an instance of a lazy expression `MpzAddExpr` if and only if *both* it's arguments are passed by move to the `MpzAddExpr`-constructor. This is possible to statically detect in `auto-ref`-passing *free* functions such as auto add()(auto ref const MpZ a, auto ref const MpZ b) { static if (!isRef!a && !isRef!b) // both r-values { // PROBLEM!!!: this case cannot be implemented // in operator overloads because // __traits(isRef, this) is incorrectly always true // safe nogc and no-RC lazy evaluation is possible return MpZAddExpr!(MpZ, MpZ)(move(a), move(b)); } else static if (!isRef!a) // r-value a { // `a` is an r-value and can be added in-place as mpz_add(a._ptr, a._ptr, b._rhs) return move(a); of type MpZ } else static if (!isRef!b) // r-value b { // `b` is an r-value and can be added in-place as mpz_add(b._ptr, b._ptr, a._rhs) // commutative return move(b); // of type MpZ } else // both references { // direct evaluation is needed Z c; // separate allocation needed mpz_add(c._ptr, a._ptr, b._ptr); return c; // of type MpZ } } because parameters are passed by D's clever `auto-ref` semantics. But the same behaviour *cannot* be implemented using operator overloads for, in this case, `opBinary`-plus. The problem boils down to the fact that __traits(isRef, this) in members such as struct S { opUnary(string)() if (s == "-") { pragma(msg, __traits(isRef, this)); } } evaluates to true in expressions such as -(S.init) eventhough `S` here clearly is an r-value. This blocks the library from applying nice optimizations during the evaluation of these lazily-evaluted expressions if operator oveloading is to be used. I expected this to be fixed by qualifying the member as `auto ref` opUnary(string)() auto ref if (s == "-") but that errors. Is this by design or by accident? Is there a way around this problem? For details see MpZ at https://github.com/nordlow/gmp-d/blob/master/src/gmp.d#L38 MpZAddExpr https://github.com/nordlow/gmp-d/blob/master/src/gmp.d#L1835
Jan 18 2017
On Wednesday, 18 January 2017 at 10:49:43 UTC, Nordlöw wrote:https://github.com/nordlow/gmp-d/blob/master/src/gmp.d#L1835Should be https://github.com/nordlow/gmp-d/blob/master/src/gmp.d#L1853
Jan 18 2017
On Wednesday, 18 January 2017 at 10:49:43 UTC, Nordlöw wrote:Is there a way around this problem?I had the same problem with opSliceAssign, opIndexAssign lately.
Jan 18 2017