Rename type/var for partial_range begin/end

- UO -> index_begin_type
- o -> index_begin
- UL -> index_end_type
- l -> index_end
- I -> range_exception

The original names were picked because `l` was the length of the
subrange.  Rename these to more closely follow STL's begin/end
nomenclature.

`I` was used variously for an iterator type and for the exception type
thrown on error.  Rename the latter to be descriptive.
This commit is contained in:
Kp 2021-09-04 12:17:14 +00:00
parent 23f03d0a5e
commit 45d72183ce

View file

@ -196,8 +196,8 @@ namespace partial_range_detail
namespace { namespace {
template <typename I, std::size_t required_buffer_size> template <typename range_exception, std::size_t required_buffer_size>
inline void check_range_bounds(const char *file, unsigned line, const char *estr, const uintptr_t t, const std::size_t o, const std::size_t l, const std::size_t d) inline void check_range_bounds(const char *file, unsigned line, const char *estr, const uintptr_t t, const std::size_t index_begin, const std::size_t index_end, const std::size_t d)
{ {
#ifdef DXX_CONSTANT_TRUE #ifdef DXX_CONSTANT_TRUE
/* /*
@ -230,21 +230,33 @@ inline void check_range_bounds(const char *file, unsigned line, const char *estr
#endif #endif
#define PARTIAL_RANGE_CHECK_BOUND(EXPR,S) \ #define PARTIAL_RANGE_CHECK_BOUND(EXPR,S) \
PARTIAL_RANGE_COMPILE_CHECK_BOUND(EXPR,S), \ PARTIAL_RANGE_COMPILE_CHECK_BOUND(EXPR,S), \
((EXPR > d) && (I::template report<required_buffer_size>(file, line, estr, #S, EXPR, t, d), 0)) ((EXPR > d) && (range_exception::template report<required_buffer_size>(file, line, estr, #S, EXPR, t, d), 0))
PARTIAL_RANGE_CHECK_BOUND(o, begin); PARTIAL_RANGE_CHECK_BOUND(index_begin, begin);
PARTIAL_RANGE_CHECK_BOUND(l, end); PARTIAL_RANGE_CHECK_BOUND(index_end, end);
#undef PARTIAL_RANGE_CHECK_BOUND #undef PARTIAL_RANGE_CHECK_BOUND
#undef PARTIAL_RANGE_COMPILE_CHECK_BOUND #undef PARTIAL_RANGE_COMPILE_CHECK_BOUND
} }
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE #ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
template <typename I, std::size_t required_buffer_size, typename P> template <typename range_exception, std::size_t required_buffer_size, typename P>
inline void check_range_object_size(const char *file, unsigned line, const char *estr, P &ref, const std::size_t o, const std::size_t l) inline void check_range_object_size(const char *file, unsigned line, const char *estr, P &ref, const std::size_t index_begin, const std::size_t index_end)
{ {
const auto ptr = std::addressof(ref); const auto ptr = std::addressof(ref);
/* Get the size of the object, according to the compiler's data
* analysis. If a size is known, check that the index values are in
* range. If no size is known, do nothing.
*
* The compiler may return a value of "unknown" here if the target
* object is dynamically allocated with unknown extents, or if the
* optimizer is not able to identify a specific object behind the
* pointer. The latter could happen if the object has a fixed size
* assigned in a different translation unit, and only the pointer to
* the object is visible in the translation unit evaluating this
* function.
*/
const std::size_t bos = __builtin_object_size(ptr, 1); const std::size_t bos = __builtin_object_size(ptr, 1);
if (bos != static_cast<std::size_t>(-1)) if (bos != static_cast<std::size_t>(-1))
check_range_bounds<I, required_buffer_size>(file, line, estr, reinterpret_cast<uintptr_t>(ptr), o, l, bos / sizeof(P)); check_range_bounds<range_exception, required_buffer_size>(file, line, estr, reinterpret_cast<uintptr_t>(ptr), index_begin, index_end, bos / sizeof(P));
} }
/* When P refers to a temporary, this overload is picked. Temporaries /* When P refers to a temporary, this overload is picked. Temporaries
@ -252,7 +264,7 @@ inline void check_range_object_size(const char *file, unsigned line, const char
* be present if iterator.operator*() returns a proxy object, rather * be present if iterator.operator*() returns a proxy object, rather
* than a reference to an element in the container. * than a reference to an element in the container.
*/ */
template <typename I, std::size_t required_buffer_size, typename P> template <typename range_exception, std::size_t required_buffer_size, typename P>
void check_range_object_size(const char *, unsigned, const char *, const P &&, std::size_t, std::size_t) {} void check_range_object_size(const char *, unsigned, const char *, const P &&, std::size_t, std::size_t) {}
#endif #endif
@ -264,22 +276,22 @@ namespace {
template <typename I, std::size_t required_buffer_size> template <typename I, std::size_t required_buffer_size>
[[nodiscard]] [[nodiscard]]
inline partial_range_t<I> (unchecked_partial_range)(const char *const file, const unsigned line, const char *const estr, I range_begin, const std::size_t o, const std::size_t l) inline partial_range_t<I> (unchecked_partial_range)(const char *const file, const unsigned line, const char *const estr, I range_begin, const std::size_t index_begin, const std::size_t index_end)
{ {
#ifdef DXX_CONSTANT_TRUE #ifdef DXX_CONSTANT_TRUE
/* Compile-time only check. Runtime handles (o > l) correctly, and /* Compile-time only check. Runtime handles (index_begin >
* it can happen in a correct program. If it is guaranteed to * index_end) correctly, and it can happen in a correct program. If
* happen, then the range is always empty, which likely indicates a * it is guaranteed to happen, then the range is always empty, which
* bug. * likely indicates a bug.
*/ */
if (DXX_CONSTANT_TRUE(!(o < l))) if (DXX_CONSTANT_TRUE(!(index_begin < index_end)))
DXX_ALWAYS_ERROR_FUNCTION(partial_range_is_always_empty, "offset never less than length"); DXX_ALWAYS_ERROR_FUNCTION(partial_range_is_always_empty, "offset never less than length");
#endif #endif
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE #ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
/* Avoid iterator dereference if range is empty */ /* Avoid iterator dereference if range is empty */
if (l) if (index_end)
{ {
partial_range_detail::check_range_object_size<typename partial_range_t<I>::partial_range_error, required_buffer_size>(file, line, estr, *range_begin, o, l); partial_range_detail::check_range_object_size<typename partial_range_t<I>::partial_range_error, required_buffer_size>(file, line, estr, *range_begin, index_begin, index_end);
} }
#else #else
(void)file; (void)file;
@ -287,64 +299,92 @@ inline partial_range_t<I> (unchecked_partial_range)(const char *const file, cons
(void)estr; (void)estr;
#endif #endif
auto range_end = range_begin; auto range_end = range_begin;
/* Use <= so that (o == 0) makes the expression always-true, so the /* Use <= so that (index_begin == 0) makes the expression
* compiler will optimize out the test. * always-true, so the compiler will optimize out the test.
*/ */
if (o <= l) if (index_begin <= index_end)
{ {
using std::advance; using std::advance;
advance(range_begin, o); advance(range_begin, index_begin);
advance(range_end, l); advance(range_end, index_end);
} }
return {range_begin, range_end}; return {range_begin, range_end};
} }
template <typename I, typename UO, typename UL, std::size_t NF, std::size_t NE> template <typename I,
typename index_begin_type,
typename index_end_type,
std::size_t NF,
std::size_t NE
>
[[nodiscard]] [[nodiscard]]
inline partial_range_t<I> (unchecked_partial_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], I range_begin, const UO &o, const UL &l) inline partial_range_t<I> (unchecked_partial_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], I range_begin, const index_begin_type &index_begin, const index_end_type &index_end)
{ {
/* Require unsigned length */ /* Require unsigned length */
static_assert(std::is_unsigned<UO>::value, "offset to partial_range must be unsigned"); static_assert(std::is_unsigned<index_begin_type>::value, "offset to partial_range must be unsigned");
static_assert(std::is_unsigned<UL>::value, "length to partial_range must be unsigned"); static_assert(std::is_unsigned<index_end_type>::value, "length to partial_range must be unsigned");
return unchecked_partial_range<I, partial_range_detail::required_buffer_size<NF, NE>>( return unchecked_partial_range<I, partial_range_detail::required_buffer_size<NF, NE>>(
file, line, estr, range_begin, o, l file, line, estr, range_begin, index_begin, index_end
); );
} }
template <typename I, typename UL, std::size_t NF, std::size_t NE> template <typename I,
typename index_end_type,
std::size_t NF,
std::size_t NE
>
[[nodiscard]] [[nodiscard]]
inline partial_range_t<I> (unchecked_partial_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], I range_begin, const UL &l) inline partial_range_t<I> (unchecked_partial_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], I range_begin, const index_end_type &index_end)
{ {
return unchecked_partial_range<I, UL, UL>(file, line, estr, range_begin, 0, l); return unchecked_partial_range<I, index_end_type, index_end_type>(file, line, estr, range_begin, 0, index_end);
} }
template <typename T, typename UO, typename UL, std::size_t NF, std::size_t NE, typename I = decltype(std::begin(std::declval<T &>()))> template <typename T,
typename index_begin_type,
typename index_end_type,
std::size_t NF,
std::size_t NE,
typename I = decltype(std::begin(std::declval<T &>()))
>
[[nodiscard]] [[nodiscard]]
inline partial_range_t<I> (partial_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], T &t, const UO &o, const UL &l) inline partial_range_t<I> (partial_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], T &t, const index_begin_type &index_begin, const index_end_type &index_end)
{ {
partial_range_detail::check_range_bounds<typename partial_range_t<I>::partial_range_error, partial_range_detail::required_buffer_size<NF, NE>>(file, line, estr, reinterpret_cast<uintptr_t>(std::addressof(t)), o, l, std::size(t)); partial_range_detail::check_range_bounds<typename partial_range_t<I>::partial_range_error, partial_range_detail::required_buffer_size<NF, NE>>(file, line, estr, reinterpret_cast<uintptr_t>(std::addressof(t)), index_begin, index_end, std::size(t));
return unchecked_partial_range<I, UO, UL>(file, line, estr, std::begin(t), o, l); return unchecked_partial_range<I, index_begin_type, index_end_type>(file, line, estr, std::begin(t), index_begin, index_end);
} }
template <typename T, typename UL, std::size_t NF, std::size_t NE> template <typename T,
typename index_end_type,
std::size_t NF,
std::size_t NE
>
[[nodiscard]] [[nodiscard]]
inline auto (partial_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], T &t, const UL &l) inline auto (partial_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], T &t, const index_end_type &index_end)
{ {
return partial_range<T, UL, UL>(file, line, estr, t, 0, l); return partial_range<T, index_end_type, index_end_type>(file, line, estr, t, 0, index_end);
} }
template <typename T, typename UO, typename UL, std::size_t NF, std::size_t NE> template <typename T,
typename index_begin_type,
typename index_end_type,
std::size_t NF,
std::size_t NE
>
[[nodiscard]] [[nodiscard]]
inline auto (partial_const_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], const T &t, const UO &o, const UL &l) inline auto (partial_const_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], const T &t, const index_begin_type &index_begin, const index_end_type &index_end)
{ {
return partial_range<const T, UO, UL>(file, line, estr, t, o, l); return partial_range<const T, index_begin_type, index_end_type>(file, line, estr, t, index_begin, index_end);
} }
template <typename T, typename UL, std::size_t NF, std::size_t NE> template <typename T,
typename index_end_type,
std::size_t NF,
std::size_t NE
>
[[nodiscard]] [[nodiscard]]
inline auto (partial_const_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], const T &t, const UL &l) inline auto (partial_const_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], const T &t, const index_end_type &index_end)
{ {
return partial_range<const T, UL>(file, line, estr, t, l); return partial_range<const T, index_end_type>(file, line, estr, t, index_end);
} }
template <typename T, typename I = decltype(std::begin(std::declval<T &>()))> template <typename T, typename I = decltype(std::begin(std::declval<T &>()))>
@ -359,11 +399,22 @@ inline partial_range_t<I> (make_range)(T &t)
/* Explicitly block use on rvalue t because returned partial_range_t<I> /* Explicitly block use on rvalue t because returned partial_range_t<I>
* will outlive the rvalue. * will outlive the rvalue.
*/ */
template <typename T, typename UO, typename UL, std::size_t NF, std::size_t NE, typename I = decltype(begin(std::declval<T &&>()))> template <typename T,
partial_range_t<I> (partial_const_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], const T &&t, const UO &o, const UL &l) = delete; typename index_begin_type,
typename index_end_type,
std::size_t NF,
std::size_t NE,
typename I = decltype(begin(std::declval<T &&>()))
>
partial_range_t<I> (partial_const_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], const T &&t, const index_begin_type &index_begin, const index_end_type &index_end) = delete;
template <typename T, typename UL, std::size_t NF, std::size_t NE, typename I = decltype(begin(std::declval<T &&>()))> template <typename T,
partial_range_t<I> (partial_const_range)(const char (&file)[NF], unsigned line, const char (&estr)[NE], const T &&t, const UL &l) = delete; typename index_end_type,
std::size_t NF,
std::size_t NE,
typename I = decltype(begin(std::declval<T &&>()))
>
partial_range_t<I> (partial_const_range)(const char (&file)[NF], const unsigned line, const char (&estr)[NE], const T &&t, const index_end_type &index_end) = delete;
#define unchecked_partial_range(T,...) unchecked_partial_range(__FILE__, __LINE__, #T, T, ##__VA_ARGS__) #define unchecked_partial_range(T,...) unchecked_partial_range(__FILE__, __LINE__, #T, T, ##__VA_ARGS__)
#define partial_range(T,...) partial_range(__FILE__, __LINE__, #T, T, ##__VA_ARGS__) #define partial_range(T,...) partial_range(__FILE__, __LINE__, #T, T, ##__VA_ARGS__)