www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Range non-emptyness assertions and opIndex

reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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
next sibling parent reply ag0aep6g <anonymous example.com> writes:
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
parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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
prev sibling parent Rene Zwanenburg <renezwanenburg gmail.com> writes:
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