martinmoene / span-lite

span lite - A C++20-like span for C++98, C++11 and later in a single-file header-only library
Boost Software License 1.0
495 stars 40 forks source link

Option to disable bound checking in operator[]? #70

Closed traversc closed 2 years ago

traversc commented 2 years ago

In a benchmark for an application, switching to nonstd::span (instead of passing raw pointer and size) resulted in a 2x performance decrease. This was due to the bound checking line for the bracket operator:

span_EXPECTS( detail::is_positive( idx ) && idx < size() );

The default behavior for std::span is to not do bound checking:

"Returns a reference to the idx-th element of the sequence. The behavior is undefined if idx is out of range (i.e., if it is greater than or equal to size())." https://en.cppreference.com/w/cpp/container/span/operator_at

So I believe that behavior should be mirrored or given as a config option.

martinmoene commented 2 years ago

Thanks for your interest in nonstd::span.

Please note that bounds checking in nonstd::span is already configurable via macros span_CONFIG_CONTRACT_LEVEL_*, see section Contract violation response macros.

traversc commented 2 years ago

Thanks for the explanation. One more question if you don't mind. I don't see span_ENSURES used anywhere in span.hpp. What is it's purpose?

martinmoene commented 2 years ago

Expects is used to enforce preconditions, ensures would be used to enforce postconditions as in design by contract. Indeed, span_ENSURES() isn't (yet) used as you observed.

In the source code:

# define span_EXPECTS( cond )  span_CONTRACT_CHECK( "Precondition", cond ) // line 503
# define span_ENSURES( cond )  span_CONTRACT_CHECK( "Postcondition", cond ) // line 511