120 lines
4.0 KiB
C++
120 lines
4.0 KiB
C++
// Copyright (c) OpenMMLab. All rights reserved.
|
|
|
|
#ifndef MMDEPLOY_SRC_CORE_MPL_SPAN_H_
|
|
#define MMDEPLOY_SRC_CORE_MPL_SPAN_H_
|
|
|
|
#include <iterator>
|
|
#include <type_traits>
|
|
|
|
#include "detected.h"
|
|
#include "iterator.h"
|
|
|
|
namespace mmdeploy {
|
|
|
|
namespace detail {
|
|
|
|
template <typename T>
|
|
using arrow_t = decltype(std::declval<T>().operator->());
|
|
|
|
template <typename T>
|
|
constexpr auto to_address(const T& p) noexcept {
|
|
if constexpr (std::is_pointer_v<T>) {
|
|
return p;
|
|
} else if (detail::is_detected_v<arrow_t, T>) {
|
|
return to_address(p.operator->());
|
|
}
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
template <typename T>
|
|
class Span {
|
|
public:
|
|
using element_type = T;
|
|
using value_type = std::remove_cv_t<T>;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = T*;
|
|
using const_pointer = const T*;
|
|
using reference = T&;
|
|
using const_reference = const T&;
|
|
using iterator = T*;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
public:
|
|
constexpr Span() noexcept : data_(nullptr), size_(0) {}
|
|
|
|
// clang-format off
|
|
template <typename It,
|
|
std::void_t<decltype(std::addressof(std::declval<It&>()))>* = nullptr>
|
|
// clang-format on
|
|
constexpr Span(It first, size_type size) : data_(detail::to_address(first)), size_(size) {}
|
|
|
|
template <typename It, typename End,
|
|
std::enable_if_t<!std::is_convertible_v<End, std::size_t>, int> = 0>
|
|
constexpr Span(It first, End last) : data_(detail::to_address(first)), size_(last - first) {}
|
|
|
|
template <typename U, typename = std::void_t<decltype(std::data(std::declval<U>()))>,
|
|
typename = std::void_t<decltype(std::size(std::declval<U>()))>>
|
|
constexpr Span(U& v) : data_(std::data(v)), size_(std::size(v)) {}
|
|
|
|
template <std::size_t N>
|
|
constexpr Span(element_type (&arr)[N]) noexcept : data_(std::data(arr)), size_(N) {}
|
|
|
|
template <std::size_t N>
|
|
constexpr Span(const Span& other) noexcept : data_(std::data(other)), size_(std::size(other)) {}
|
|
|
|
constexpr iterator begin() const noexcept { return data_; }
|
|
constexpr iterator end() const noexcept { return data_ + size_; }
|
|
constexpr reverse_iterator rbegin() const noexcept { return std::make_reverse_iterator(end()); }
|
|
constexpr reverse_iterator rend() const noexcept { return std::make_reverse_iterator(begin()); }
|
|
constexpr reference front() const { return data_[0]; }
|
|
constexpr reference back() const { return data_[size_ - 1]; }
|
|
constexpr reference operator[](size_type idx) const { return data_[idx]; }
|
|
constexpr pointer data() const noexcept { return data_; }
|
|
constexpr size_type size() const noexcept { return size_; }
|
|
constexpr size_type size_bytes() const noexcept { return sizeof(value_type) * size(); }
|
|
constexpr bool empty() const noexcept { return size_ == 0; }
|
|
constexpr Span<element_type> first(size_type count) const { return {begin(), count}; }
|
|
constexpr Span<element_type> last(size_type count) const { return {end() - count, count}; }
|
|
constexpr Span<element_type> subspan(size_type offset, size_type count = -1) const {
|
|
if (count == -1) {
|
|
return {begin() + offset, end()};
|
|
} else {
|
|
return {begin() + offset, begin() + offset + count};
|
|
}
|
|
}
|
|
|
|
constexpr Span& operator=(const Span& other) noexcept = default;
|
|
|
|
friend bool operator==(const Span& a, const Span& b) {
|
|
if (a.size() != b.size()) return false;
|
|
for (size_type i = 0; i < a.size(); ++i) {
|
|
if (a[i] != b[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
friend bool operator!=(const Span& a, const Span& b) { return !(a == b); }
|
|
|
|
private:
|
|
T* data_;
|
|
size_type size_;
|
|
};
|
|
// clang-format off
|
|
template <typename It, typename EndOrSize>
|
|
Span(It, EndOrSize) -> Span<std::remove_reference_t<iter_reference_t<It>>>;
|
|
|
|
template <typename T, std::size_t N>
|
|
Span(T (&)[N]) -> Span<T>;
|
|
|
|
template <typename U, typename = std::void_t<decltype(std::declval<U>().data())>,
|
|
typename = std::void_t<decltype(std::declval<U>().size())>>
|
|
Span(U& v) -> Span<typename uncvref_t<U>::value_type>;
|
|
// clang-format on
|
|
} // namespace mmdeploy
|
|
|
|
#endif // MMDEPLOY_SRC_CORE_MPL_SPAN_H_
|