|
16 | 16 |
|
17 | 17 | #include "test_macros.h"
|
18 | 18 |
|
| 19 | +// Tests whether the pointer p is in the range [first, last). |
| 20 | +// |
| 21 | +// Precondition: The range [first, last) is a valid range. |
| 22 | +// |
| 23 | +// Typically the pointers are compared with less than. This is not allowed when |
| 24 | +// the pointers belong to different ranges, which 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 p is in the range [first, last) the data can be copied from the |
| 30 | +// beginning to the end. Otherwise it needs to be copied from the end to the |
| 31 | +// beginning. |
| 32 | +template <class CharT> |
| 33 | +TEST_CONSTEXPR_CXX14 bool is_pointer_in_range(const CharT* first, const CharT* last, const CharT* p) { |
| 34 | + if (first == p) // Needed when n == 0 |
| 35 | + return true; |
| 36 | + |
| 37 | + for (; first != last; ++first) |
| 38 | + if (first == p) |
| 39 | + return true; |
| 40 | + |
| 41 | + return false; |
| 42 | +} |
| 43 | + |
19 | 44 | template <class CharT>
|
20 | 45 | struct constexpr_char_traits
|
21 | 46 | {
|
@@ -98,23 +123,21 @@ constexpr_char_traits<CharT>::find(const char_type* s, std::size_t n, const char
|
98 | 123 | }
|
99 | 124 |
|
100 | 125 | 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; |
| 126 | +TEST_CONSTEXPR_CXX14 CharT* constexpr_char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n) { |
| 127 | + if (s1 == s2) |
| 128 | + return s1; |
| 129 | + |
| 130 | + char_type* r = s1; |
| 131 | + if (is_pointer_in_range(s1, s1 + n, s2)) { |
| 132 | + for (; n; --n) |
| 133 | + assign(*s1++, *s2++); |
| 134 | + } else { |
| 135 | + s1 += n; |
| 136 | + s2 += n; |
| 137 | + for (; n; --n) |
| 138 | + assign(*--s1, *--s2); |
| 139 | + } |
| 140 | + return r; |
118 | 141 | }
|
119 | 142 |
|
120 | 143 | template <class CharT>
|
|
0 commit comments