On Saturday, 25 February 2017 at 19:59:29 UTC, ikod wrote:
Hello,I have a method for range: struct Range { immutable(ubyte[]) _buffer; size_t _pos; @property void popFront() pure @safe {enforce(_pos < _buffer.length, "popFront from empty buffer");_pos++; } }I'd like to have @nogc here, but I can't because enforce() is non-@nogc. I have a trick but not sure if it is valid, especially I don't know if optimization will preserve code, used for throwing:import std.string; struct Range { immutable(ubyte[]) _buffer; size_t _pos; this(immutable(ubyte[]) s) { _buffer = s; } @property void popFront() pure @safe @nogc { if (_pos >= _buffer.length ) { auto _ = _buffer[$]; // throws RangeError } _pos++; } } void main() { auto r = Range("1".representation); r.popFront(); r.popFront(); // throws } Is it ok to use it? Is there any better solution? Thanks!
You can wrap a gc function in a nogc call using a function pointer that casts it to a nogc. You do this first by casting to void* then back to the same signature as the function + @nogc. This "tricks" the compiler in to calling the gc function from a nogc function. The problem is, of course, it is not safe if the gc is turned off as it will result in a memory leak. This may or may not be an issue with enforce depending on if it allocates before or after the check.
