mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-10 10:52:31 -05:00
span: add lifetimebound attribute
See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0936r0.pdf for reference. This helps to guard against dangling references caused by construction from temporaries such as: Span<const int> sp(std::vector<int>{1,2,3});
This commit is contained in:
parent
62733fee87
commit
1d58cc7cb0
1 changed files with 14 additions and 4 deletions
18
src/span.h
18
src/span.h
|
@ -18,6 +18,16 @@
|
||||||
#define ASSERT_IF_DEBUG(x)
|
#define ASSERT_IF_DEBUG(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#if __has_attribute(lifetimebound)
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND [[clang::lifetimebound]]
|
||||||
|
#else
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND
|
||||||
|
#endif
|
||||||
|
|
||||||
/** A Span is an object that can refer to a contiguous sequence of objects.
|
/** A Span is an object that can refer to a contiguous sequence of objects.
|
||||||
*
|
*
|
||||||
* It implements a subset of C++20's std::span.
|
* It implements a subset of C++20's std::span.
|
||||||
|
@ -87,14 +97,14 @@ public:
|
||||||
* Note that this restriction does not exist when converting arrays or other Spans (see above).
|
* Note that this restriction does not exist when converting arrays or other Spans (see above).
|
||||||
*/
|
*/
|
||||||
template <typename V>
|
template <typename V>
|
||||||
constexpr Span(V& other,
|
constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND,
|
||||||
typename std::enable_if<!is_Span<V>::value &&
|
typename std::enable_if<!is_Span<V>::value &&
|
||||||
std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value &&
|
std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value &&
|
||||||
std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
||||||
: m_data(other.data()), m_size(other.size()){}
|
: m_data(other.data()), m_size(other.size()){}
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
constexpr Span(const V& other,
|
constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND,
|
||||||
typename std::enable_if<!is_Span<V>::value &&
|
typename std::enable_if<!is_Span<V>::value &&
|
||||||
std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value &&
|
std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value &&
|
||||||
std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
||||||
|
@ -154,9 +164,9 @@ public:
|
||||||
/** MakeSpan for arrays: */
|
/** MakeSpan for arrays: */
|
||||||
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
||||||
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
|
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
|
||||||
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); }
|
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); }
|
||||||
/** MakeSpan for (lvalue) references, supporting mutable output. */
|
/** MakeSpan for (lvalue) references, supporting mutable output. */
|
||||||
template <typename V> constexpr auto MakeSpan(V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
|
template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
|
||||||
|
|
||||||
/** Pop the last element off a span, and return a reference to that element. */
|
/** Pop the last element off a span, and return a reference to that element. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
Loading…
Add table
Reference in a new issue