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!
solution 1/
===
You can throw a static Exception.
auto staticEx(string msg, string file = __FILE__, size_t line =
__LINE__)() @nogc
{
immutable static Exception e = new Exception(msg, file, line);
return e;
}
void main() @nogc
{
throw staticEx!"bla";
}
not good for the call stack display, tho.
solution 2/
===
Throw an Error. Errors shouldn't be caugth and consequently they
lead to program termination so you don't care about the leak.
import std.experimental.allocator: make;
import std.experimental.allocator.mallocator: Mallocator;
void main() @nogc
{
throw make!Error(Mallocator.instance, "bla");
}
good when errors are not designed to be caught. not good for
exceptions because might leak to death depending on how the
exceptions happens (i.e in a loop ouch).
solution 3/
===
Reference counting. Not explored so far.
To finish, using a assert(0) is bad. assert(0) throws an error,
it's really not like an Exception.