Since this should never be invoked, simplify the definition. The new
version is slightly less informative in case a logic error causes it to
be called, but is far shorter and easier to understand.
The concept std::ranges::range<T> requires that std::ranges::end(T) be
well-formed. An input with a `const` qualified member fails this test,
and causes std::ranges::range<T> to reject an otherwise satisfiable
range.
Compiler error messages are generally better when reporting a misuse
that fails a requires() versus reporting a misuse that fails a
std::enable_if. In some cases, this also makes the code clearer, and
avoids the need for dummy template parameters as a place to invoke
std::enable_if.
AlumiuN reports that mingw32-w64-gcc-8.1.0 incorrectly reports
`ascending` as unused-but-set. This is clearly not true. Reorder the
code to avoid saving `ascending`, and instead use the result of
`detail::get_xrange_ascending` directly. This also improves the error
message in the DXX_ALWAYS_ERROR_FUNCTION path.
Reported-by: AlumiuN <https://github.com/dxx-rebirth/dxx-rebirth/issues/626>
clang chokes on use of a `constexpr bool` that is initialized separately
from its definition. gcc allows this. Move the value computation into
a constexpr helper function, so that the variable can be defined and
initialized in the same statement.
Iterating over it returns each side number in turn. This allows
converting many loops of the form:
```
for (int i = 0; i < MAX_SIDES_PER_SEGMENT; ++i)
```
to the compact form:
```
for (const auto i : MAX_SIDES_PER_SEGMENT)
```
The compact form brings the usual benefit of range-based for: delegating
iteration to the compiler prevents the loop body from skipping a step,
and makes clear in the code that this is the case.
Prior to this, an xrange always started at the begin term and
incremented by 1 per step until it reached the end term. There was no
support for a step size other than 1. Add support for custom step size.
It is the caller's responsibility to pick a step size that will
eventually lead to (iter != end) evaluating to false.
std::find_if needs common iterator traits. Add the relevant type
definitions to zip_iterator.
Also add them to d_range, to avoid errors when a range is zipped.
gcc-9 rejects `std::enable_if<false,
std::integral_constant<std::integral_constant, 1> 0>::type` before it
notices that the whole expression is eliminated due to SFINAE. Use
`std::common_type` to coerce the inner integral_constant to an
appropriate integer type, which allows the expression to be well-formed
enough to reach the SFINAE check from enable_if, then be silently
removed from the overload resolution set.
Utility xrange, inspired by the Python2 feature of the same name,
provides an object that returns successive values from [start, end). It
is useful when the end index is known in advance, and is particularly
helpful when that index is expensive to recompute.