...
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 | ||||
|---|---|---|---|---|
| ||||
#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
pandqcompare equal,p<=qandp>=qboth yieldtrueandp<qandp>qboth yieldfalse. Otherwise, if a pointerpcompares greater than a pointerq,p>=q,p>q,q<=p, andq<pall yieldtrueandp<=q,p<q,q>=p, andq>pall yieldfalse. 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, andless_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.
...