trick to make throwing method @nogc

Eugene Wissner via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Feb 25 12:40:26 PST 2017


On Saturday, 25 February 2017 at 20:02:56 UTC, ikod wrote:
> 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- at 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!
>
> Found that I can use
>
>     @property void popFront() pure @safe @nogc {
>         if (_pos >= _buffer.length ) {
> 			assert(0, "popFront for empty range");
>         }
>         _pos++;
>     }
>
> which is both descriptive and can't be optimized out.

I made a test:

void main()
{
   assert(0);
}

it builds and doesn't throw if I compile with:
dmd -release

though it causes a segfault, what is probably a dmd bug. So I 
suppose it can be optimized out. And it isn't very discriptive, 
you probably throws the same AssertError for all errors. You can 
throw in @nogc code, you only have to allocate the exception not 
on the GC heap and free it after catching. I'm writing myself a 
library that is complete @nogc and I use exceptions this way:
- Allocate the exception
- throw
- catch
- free

A wrapper that unifies these 4 steps like enforce is pretty easy 
to implement.


More information about the Digitalmars-d-learn mailing list