digitalmars.D.learn - Range non-emptyness assertions and opIndex
- =?UTF-8?B?Tm9yZGzDtnc=?= (50/50) Jul 01 2016 If I have a typical range definition like the following
- ag0aep6g (21/31) Jul 01 2016 I think assert is the most common way of checking. Simply ignoring the
- =?UTF-8?B?Tm9yZGzDtnc=?= (2/5) Jul 01 2016 Aha, that's what I was testing against so therefore the confusion.
- Rene Zwanenburg (38/41) Jul 01 2016 Asserts are removed in release mode, enforce isn't. Here's an
If I have a typical range definition like the following struct Range { safe pure nogc: bool empty() const nothrow { return _i == _j; } size_t length() const nothrow { return _j - _i; } bool front() const { assert(!empty); // TODO use enforce when it's nogc return _store[_i]; } bool back() const { assert(!empty); // TODO use enforce when it's nogc return _store[_j - 1]; } void popFront() { assert(!empty); ++_i; } void popBack() { assert(!empty); ++_i; } private: BitSet _store; // copy of store size_t _i = 0; // iterator into _store size_t _j = _store.length; } What's the preferred way of reacting to emptyness in the members front, back, popFront, popBack --- using assert, enforce, throw, or simply relying on range-checking in the _store? And what about using debug assert() instead of assert() typically when `_store`s `opIndex` already performs range-checking? I think this is a important issue since asserts are not optimized away in release mode and D is very much about performance.
Jul 01 2016
On 07/01/2016 12:35 PM, Nordlöw wrote:What's the preferred way of reacting to emptyness in the members front, back, popFront, popBack --- using assert, enforce, throw, or simply relying on range-checking in the _store?I think assert is the most common way of checking. Simply ignoring the possibility is also common, as it's considered a programming error to call front/popFront/etc on an empty range. For the same reason, throwing an exception (via throw or via enforce) is less common. Exceptions are more for input/environment errors, not so much for programming errors.And what about using debug assert() instead of assert() typically when `_store`s `opIndex` already performs range-checking? I think this is a important issue since asserts are not optimized away in release mode and D is very much about performance.Huh? Asserts are ignored with -release. The only exception is assert(false) which terminates the program immediately, even with -release. A little example program: ---- void main() { import std.stdio; int x = 1; assert(x != 1); writeln("hi"); } ---- When compiled without -release, the program throws an AssertError. With -release it prints "hi".
Jul 01 2016
On Friday, 1 July 2016 at 11:35:40 UTC, ag0aep6g wrote:Huh? Asserts are ignored with -release. The only exception is assert(false) which terminates the program immediately, even with -release.Aha, that's what I was testing against so therefore the confusion.
Jul 01 2016
On Friday, 1 July 2016 at 10:35:04 UTC, Nordlöw wrote:I think this is a important issue since asserts are not optimized away in release mode and D is very much about performance.Asserts are removed in release mode, enforce isn't. Here's an example: ===== void main(string[] args) { assert(args.length >= 1); } ===== dmd testfile.d This calls the assert function as expected: ===== _Dmain: 0000000000000000: 55 push rbp 0000000000000001: 48 8B EC mov rbp,rsp 0000000000000004: 48 83 39 01 cmp qword ptr [rcx],1 0000000000000008: 73 0E jae 0000000000000018 000000000000000A: B9 03 00 00 00 mov ecx,3 000000000000000F: 48 83 EC 20 sub rsp,20h 0000000000000013: E8 00 00 00 00 call _D5test28__assertFiZv 0000000000000018: 31 C0 xor eax,eax 000000000000001A: 5D pop rbp 000000000000001B: C3 ret ===== Now compiling in release mode: dmd -release testfile.d No assert in sight: ===== _Dmain: 0000000000000000: 55 push rbp 0000000000000001: 48 8B EC mov rbp,rsp 0000000000000004: 31 C0 xor eax,eax 0000000000000006: 5D pop rbp 0000000000000007: C3 ret =====
Jul 01 2016