|
18 | 18 | #define ASSERT_IF_DEBUG(x)
|
19 | 19 | #endif
|
20 | 20 |
|
| 21 | +#if defined(__clang__) |
| 22 | +#if __has_attribute(lifetimebound) |
| 23 | +#define SPAN_ATTR_LIFETIMEBOUND [[clang::lifetimebound]] |
| 24 | +#else |
| 25 | +#define SPAN_ATTR_LIFETIMEBOUND |
| 26 | +#endif |
| 27 | +#else |
| 28 | +#define SPAN_ATTR_LIFETIMEBOUND |
| 29 | +#endif |
| 30 | + |
21 | 31 | /** A Span is an object that can refer to a contiguous sequence of objects.
|
22 | 32 | *
|
23 | 33 | * It implements a subset of C++20's std::span.
|
@@ -87,14 +97,14 @@ class Span
|
87 | 97 | * Note that this restriction does not exist when converting arrays or other Spans (see above).
|
88 | 98 | */
|
89 | 99 | template <typename V>
|
90 |
| - constexpr Span(V& other, |
| 100 | + constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND, |
91 | 101 | typename std::enable_if<!is_Span<V>::value &&
|
92 | 102 | std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value &&
|
93 | 103 | std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
94 | 104 | : m_data(other.data()), m_size(other.size()){}
|
95 | 105 |
|
96 | 106 | template <typename V>
|
97 |
| - constexpr Span(const V& other, |
| 107 | + constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND, |
98 | 108 | typename std::enable_if<!is_Span<V>::value &&
|
99 | 109 | std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value &&
|
100 | 110 | std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
@@ -154,9 +164,9 @@ class Span
|
154 | 164 | /** MakeSpan for arrays: */
|
155 | 165 | template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
156 | 166 | /** MakeSpan for temporaries / rvalue references, only supporting const output. */
|
157 |
| -template <typename V> constexpr auto MakeSpan(V&& v) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); } |
| 167 | +template <typename V> constexpr auto MakeSpan(V&& v SPAN_ATTR_LIFETIMEBOUND) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); } |
158 | 168 | /** MakeSpan for (lvalue) references, supporting mutable output. */
|
159 |
| -template <typename V> constexpr auto MakeSpan(V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; } |
| 169 | +template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; } |
160 | 170 |
|
161 | 171 | /** Pop the last element off a span, and return a reference to that element. */
|
162 | 172 | template <typename T>
|
|
0 commit comments