Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This noncompliant code example attempts to determine whether the pointer test is within the range [r, r + n]. However, when test does not point within the given range, as in this example, it results undefined behavior.

Code Block
bgColor#ffcccc
langcpp
#include <cstddef>
#include <iostream>
 
template <typename Ty>
bool in_range(const Ty *test, const Ty *r, size_t n) {
  return (test - r) < (std::ptrdiff_t)n;
}
 
void f() {
  double foo[10];
  double *x = &foo[0];
  double bar;
  std::cout << std::boolalpha << in_range(&bar, x, 10);
}

...

In this noncompliant code example, the in_range() function is implemented using a comparison expression instead of subtraction. The C++ Standard, [expr.rel], paragraph 4 , states [ISO/IEC 14882-2014], states:

If two operands p and q compare equal, p<=q and p>=q both yield true and p<q and p>q both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

...

This noncompliant code example is roughly equivalent to the previous example except that it uses iterators in place of raw pointers. As with the previous example, the in_range_impl() function exhibits exhibits unspecified behavior when the iterators do not refer into the same container because the operational semantics of a < b on a random access iterator are b - a > 0, and >= is implemented in terms of <.

...

In this noncompliant code example, std::less<T> is used in place of the < operator. The C++ Standard, [comparisons], paragraph 14 , states [ISO/IEC 14882-2014], states:

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

Although this approach yields a total ordering, the definition of that total ordering is still unspecified by the implementation. For instance, the following statement could result in the assertion triggering for a given, unrelated pair of pointers, a and b: assert(std::less<T *>()(a, b) == std::greater<T *>()(a, b));. Consequently, this noncompliant code example is still nonportable and, on common implementations of std::less<T>, may even result in undefined behavior when the < operator is invoked.

...