diff --git a/include/libtorrent/aux_/typed_span.hpp b/include/libtorrent/aux_/typed_span.hpp index dff6fc0f3..bb96eb710 100644 --- a/include/libtorrent/aux_/typed_span.hpp +++ b/include/libtorrent/aux_/typed_span.hpp @@ -47,8 +47,36 @@ namespace libtorrent { namespace aux { using base = span; using underlying_index = typename underlying_index_t::type; - // pull in constructors from base class - using base::base; + // disallow conversions from other index types + template + typed_span(typed_span const&) = delete; + typed_span() noexcept = default; + typed_span(typed_span const&) noexcept = default; + typed_span& operator=(typed_span const&) noexcept = default; + + template ::value>::type> + typed_span(typed_span const& v) noexcept // NOLINT + : span(v) {} + + typed_span(T& p) noexcept : span(p) {} // NOLINT + typed_span(T* p, std::size_t const l) noexcept : span(p, l) {} // NOLINT + + template + typed_span(std::array& arr) noexcept // NOLINT + : span(arr.data(), arr.size()) {} + + template + typed_span(U (&arr)[N]) noexcept // NOLINT + : span(&arr[0], N) {} + + // anything with a .data() member function is considered a container + // but only if the value type is compatible with T + template ().data())>::type + , typename = typename std::enable_if::value>::type> + typed_span(Cont& c) : span(c.data(), c.size())// NOLINT + {} auto operator[](IndexType idx) const -> #if TORRENT_AUTO_RETURN_TYPES diff --git a/include/libtorrent/span.hpp b/include/libtorrent/span.hpp index c63094b08..583eb30f9 100644 --- a/include/libtorrent/span.hpp +++ b/include/libtorrent/span.hpp @@ -64,22 +64,22 @@ namespace aux { template struct span { - span() : m_ptr(nullptr), m_len(0) {} + span() noexcept : m_ptr(nullptr), m_len(0) {} template ::value>::type> - span(span const& v) // NOLINT + span(span const& v) noexcept // NOLINT : m_ptr(v.data()), m_len(v.size()) {} - span(T& p) : m_ptr(&p), m_len(1) {} // NOLINT - span(T* p, std::size_t const l) : m_ptr(p), m_len(l) {} // NOLINT + span(T& p) noexcept : m_ptr(&p), m_len(1) {} // NOLINT + span(T* p, std::size_t const l) noexcept : m_ptr(p), m_len(l) {} // NOLINT template - span(std::array& arr) // NOLINT + span(std::array& arr) noexcept // NOLINT : m_ptr(arr.data()), m_len(arr.size()) {} template - span(U (&arr)[N]) // NOLINT + span(U (&arr)[N]) noexcept // NOLINT : m_ptr(&arr[0]), m_len(N) {} // anything with a .data() member function is considered a container @@ -90,20 +90,20 @@ namespace aux { span(Cont& c) // NOLINT : m_ptr(c.data()), m_len(c.size()) {} - std::size_t size() const { return m_len; } - bool empty() const { return m_len == 0; } - T* data() const { return m_ptr; } + std::size_t size() const noexcept { return m_len; } + bool empty() const noexcept { return m_len == 0; } + T* data() const noexcept { return m_ptr; } using iterator = T*; using reverse_iterator = std::reverse_iterator; - T* begin() const { return m_ptr; } - T* end() const { return m_ptr + m_len; } - reverse_iterator rbegin() const { return reverse_iterator(end()); } - reverse_iterator rend() const { return reverse_iterator(begin()); } + T* begin() const noexcept { return m_ptr; } + T* end() const noexcept { return m_ptr + m_len; } + reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } - T& front() const { TORRENT_ASSERT(m_len > 0); return m_ptr[0]; } - T& back() const { TORRENT_ASSERT(m_len > 0); return m_ptr[m_len - 1]; } + T& front() const noexcept { TORRENT_ASSERT(m_len > 0); return m_ptr[0]; } + T& back() const noexcept { TORRENT_ASSERT(m_len > 0); return m_ptr[m_len - 1]; } span first(std::size_t const n) const {