[phobos] enforce() vs. assert() for range primitives

David Simcha dsimcha at gmail.com
Wed Aug 18 15:49:52 PDT 2010

While I was debugging std.range and std.algorithm I noticed that there's 
tons of inconsistency about when enforce() vs. assert() is used for 
checking input to range primitives.  I think this needs to be made 
consistent, and there are good arguments for both.

enforce() is arguably the way to go because we're dealing with an 
external API, not internal consistency checks.  According to the 
guidelines in TDPL input external to an API should be checked even in 
release mode.

On the other hand, assert() is arguably the way to go because ranges are 
supposed to be a very efficient abstraction.  Having enforce() in range 
primitives that look like they should be very fast, inlined functions is 
just bad practice.  For example, some benchmarks I did awhile back 
showed that the use of enforce() and its effect on inlining can make 
using ranges slower than using opApply.  Furthermore, if you're stacking 
several higher-order ranges, i.e. filter!"a > 0"(map!"a * 
a"(retro(someArray))) the checks may be redundant.  Lastly, since arrays 
are the canonical range, omitting release mode checks in library-defined 
ranges would make them consistent with arrays.

Generally when I was debugging I tried to be locally consistent, i.e. 
use whatever was used elsewhere in the same range.  This meant being 
globally inconsistent.  Now that I've thought about it, my vote is for 
using assert() consistently for range primitives.  If ranges are filled 
with tons of safety checks that have significant performance costs and 
can't be disabled even in release mode, they will have failed in their 
goal of providing a lightweight, efficient abstraction.  enforce() can 
be used for things that are intended to be called much less frequently, 
like constructors.  Comments?

More information about the phobos mailing list