136 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
#include <utility>
 | 
						|
#include <iterator>
 | 
						|
namespace zstd
 | 
						|
{
 | 
						|
	namespace detail
 | 
						|
	{
 | 
						|
		template<typename T, typename = void>
 | 
						|
		struct is_contiguous_container : std::false_type {};
 | 
						|
 | 
						|
		template<typename T>
 | 
						|
		struct is_contiguous_container<T, std::void_t<decltype(
 | 
						|
			std::data(std::declval<T&>()),
 | 
						|
			std::size(std::declval<T&>())
 | 
						|
			)>> : std::true_type {};
 | 
						|
		template<typename T> constexpr auto is_contiguous_container_v = is_contiguous_container<T>::value;
 | 
						|
	}
 | 
						|
 | 
						|
	template <typename T>
 | 
						|
	struct span
 | 
						|
	{
 | 
						|
		static constexpr auto npos = static_cast<size_t>(-1);
 | 
						|
		using element_type = T;
 | 
						|
		using value_type = std::remove_cv_t<T>;
 | 
						|
		using size_t = 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 const_iterator = const T*;
 | 
						|
		using reverse_iterator = std::reverse_iterator<iterator>;
 | 
						|
		using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 | 
						|
 | 
						|
		T* _begin = nullptr;
 | 
						|
		T* _end = nullptr;
 | 
						|
 | 
						|
		constexpr span() noexcept = default;
 | 
						|
		constexpr span(T* begin, T* end) noexcept;
 | 
						|
		template <typename Container, typename = std::enable_if_t<detail::is_contiguous_container_v<Container>
 | 
						|
		&& std::is_convertible_v<decltype(std::data(std::declval<Container&>())), T*>
 | 
						|
			&& !std::is_same_v<std::decay_t<Container>, span>>>
 | 
						|
			constexpr span(Container&& c) noexcept;
 | 
						|
		constexpr span(const span&) noexcept = default;
 | 
						|
 | 
						|
		// element access
 | 
						|
		constexpr T& operator[](size_t index) const noexcept;
 | 
						|
		constexpr T& front() const noexcept;
 | 
						|
		constexpr T& back() const noexcept;
 | 
						|
		constexpr T* data() const noexcept;
 | 
						|
 | 
						|
		// iterators
 | 
						|
		constexpr T* begin() const noexcept;
 | 
						|
		constexpr T* end() const noexcept;
 | 
						|
 | 
						|
		// subviews
 | 
						|
		constexpr span<T> subspan(size_t offset, size_t count = npos) const noexcept;
 | 
						|
 | 
						|
		// capacity
 | 
						|
		constexpr size_t size() const noexcept;
 | 
						|
		constexpr size_t size_bytes() const noexcept;
 | 
						|
		constexpr bool empty() const noexcept;
 | 
						|
	};
 | 
						|
	//User defined deduction guide (C++17 onwards)
 | 
						|
	template<typename Container>
 | 
						|
	span(Container&&) -> span < std::remove_reference_t<decltype(*std::declval<Container>().data())>>;
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	constexpr span<T>::span(T* begin, T* end) noexcept
 | 
						|
		: _begin{ begin }, _end{ end }
 | 
						|
	{}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	template<typename Container, typename>
 | 
						|
	constexpr span<T>::span(Container&& c) noexcept
 | 
						|
		: _begin{ std::data(c) }, _end{ std::data(c) + std::size(c) }
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	constexpr T* span<T>::begin() const noexcept
 | 
						|
	{
 | 
						|
		return _begin;
 | 
						|
	}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	constexpr T* span<T>::end() const noexcept
 | 
						|
	{
 | 
						|
		return _end;
 | 
						|
	}
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr span<T> span<T>::subspan(size_t offset, size_t count) const noexcept
 | 
						|
	{
 | 
						|
		return span<T>{_begin + offset, count != npos ? _begin + offset + count : _end};
 | 
						|
	}
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr T* span<T>::data() const noexcept
 | 
						|
	{
 | 
						|
		return _begin;
 | 
						|
	}
 | 
						|
	template<typename T>
 | 
						|
	constexpr size_t span<T>::size() const noexcept
 | 
						|
	{
 | 
						|
		return _end - _begin;
 | 
						|
	}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr size_t span<T>::size_bytes() const noexcept
 | 
						|
	{
 | 
						|
		return size() * sizeof(T);
 | 
						|
	}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr bool span<T>::empty() const noexcept
 | 
						|
	{
 | 
						|
		return _begin == _end;
 | 
						|
	}
 | 
						|
 | 
						|
	template<typename T>
 | 
						|
	constexpr T& span<T>::operator[](size_t index) const noexcept
 | 
						|
	{
 | 
						|
		return _begin[index];
 | 
						|
	}
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr T& span<T>::front() const noexcept
 | 
						|
	{
 | 
						|
		return *_begin;
 | 
						|
	}
 | 
						|
	template<typename T>
 | 
						|
	inline constexpr T& span<T>::back() const noexcept
 | 
						|
	{
 | 
						|
		return _end[-1];
 | 
						|
	}
 | 
						|
}
 |