Skip to content

Commit

Permalink
Merge bitcoin#19387: span: update constructors to match c++20 draft s…
Browse files Browse the repository at this point in the history
…pec and add lifetimebound attribute

bitcoin@62733fe
bitcoin@1d58cc7
bitcoin@e3e7446
  • Loading branch information
kwvg committed Apr 23, 2021
1 parent ec2eec0 commit 5667698
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
10 changes: 10 additions & 0 deletions src/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@
# endif
#endif

#if defined(__clang__)
# if __has_attribute(lifetimebound)
# define LIFETIMEBOUND [[clang::lifetimebound]]
# else
# define LIFETIMEBOUND
# endif
#else
# define LIFETIMEBOUND
#endif

#endif // BITCOIN_ATTRIBUTES_H
37 changes: 33 additions & 4 deletions src/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
#define ASSERT_IF_DEBUG(x)
#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.
*
* It implements a subset of C++20's std::span.
Expand All @@ -28,6 +38,14 @@ class Span
C* m_data;
std::size_t m_size;

template <class T>
struct is_Span_int : public std::false_type {};
template <class T>
struct is_Span_int<Span<T>> : public std::true_type {};
template <class T>
struct is_Span : public is_Span_int<typename std::remove_cv<T>::type>{};


public:
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}

Expand Down Expand Up @@ -78,8 +96,19 @@ class Span
* To prevent surprises, only Spans for constant value types are supported when passing in temporaries.
* Note that this restriction does not exist when converting arrays or other Spans (see above).
*/
template <typename V, typename std::enable_if<(std::is_const<C>::value || std::is_lvalue_reference<V>::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, int>::type = 0>
constexpr Span(V&& v) noexcept : m_data(v.data()), m_size(v.size()) {}
template <typename V>
constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND,
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<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
: m_data(other.data()), m_size(other.size()){}

template <typename V>
constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND,
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<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
: m_data(other.data()), m_size(other.size()){}

constexpr C* data() const noexcept { return m_data; }
constexpr C* begin() const noexcept { return m_data; }
Expand Down Expand Up @@ -135,9 +164,9 @@ class Span
/** MakeSpan for arrays: */
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. */
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. */
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. */
template <typename T>
Expand Down

0 comments on commit 5667698

Please sign in to comment.