|
16 | 16 |
|
17 | 17 | #include "test_macros.h"
|
18 | 18 |
|
| 19 | +// Tests whether the range [p1, p1 + n) overlaps with the range [p2, p2 + n). |
| 20 | +// |
| 21 | +// precondition The ranges [p1, p1 + n) and [p2, p2 + n) are valid ranges. |
| 22 | +// |
| 23 | +// Typically the pointers are compared with less than. This is not allowed when |
| 24 | +// the pointers belong to different ranges. This is UB. Typically, this is |
| 25 | +// benign at run-time, however since UB is not allowed during constant |
| 26 | +// evaluation this does not compile. This function does the validation without |
| 27 | +// UB. |
| 28 | +// |
| 29 | +// When the ranges overlap the ranges can be copied from the beginning to the |
| 30 | +// end. Otherwise they need to be copied from the end to the beginning. |
| 31 | +template <class Traits> |
| 32 | +TEST_CONSTEXPR_CXX14 bool is_overlapping_range(Traits* p1, const Traits* p2, std::size_t n) { |
| 33 | + if (p1 == p2) // Needed when n == 0 |
| 34 | + return true; |
| 35 | + |
| 36 | + for (; n; --n, ++p1) |
| 37 | + if (p1 == p2) |
| 38 | + return true; |
| 39 | + |
| 40 | + return false; |
| 41 | +} |
| 42 | + |
19 | 43 | template <class CharT>
|
20 | 44 | struct constexpr_char_traits
|
21 | 45 | {
|
@@ -98,23 +122,21 @@ constexpr_char_traits<CharT>::find(const char_type* s, std::size_t n, const char
|
98 | 122 | }
|
99 | 123 |
|
100 | 124 | template <class CharT>
|
101 |
| -TEST_CONSTEXPR_CXX14 CharT* |
102 |
| -constexpr_char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n) |
103 |
| -{ |
104 |
| - char_type* r = s1; |
105 |
| - if (s1 < s2) |
106 |
| - { |
107 |
| - for (; n; --n, ++s1, ++s2) |
108 |
| - assign(*s1, *s2); |
109 |
| - } |
110 |
| - else if (s2 < s1) |
111 |
| - { |
112 |
| - s1 += n; |
113 |
| - s2 += n; |
114 |
| - for (; n; --n) |
115 |
| - assign(*--s1, *--s2); |
116 |
| - } |
117 |
| - return r; |
| 125 | +TEST_CONSTEXPR_CXX14 CharT* constexpr_char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n) { |
| 126 | + if (s1 == s2) |
| 127 | + return s1; |
| 128 | + |
| 129 | + char_type* r = s1; |
| 130 | + if (is_overlapping_range(s1, s2, n)) { |
| 131 | + for (; n; --n) |
| 132 | + assign(*s1++, *s2++); |
| 133 | + } else { |
| 134 | + s1 += n; |
| 135 | + s2 += n; |
| 136 | + for (; n; --n) |
| 137 | + assign(*--s1, *--s2); |
| 138 | + } |
| 139 | + return r; |
118 | 140 | }
|
119 | 141 |
|
120 | 142 | template <class CharT>
|
|
0 commit comments