mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
etl::poly_span without etl::dynamic_extent
This commit is contained in:
parent
26d0dd9859
commit
9dca59bf40
@ -1,208 +1,641 @@
|
||||
#pragma once
|
||||
///\file
|
||||
|
||||
#include "span/detail/poly_span_utils.h"
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
Copyright (c) 2020 Dr. Alexander Bulovyatov
|
||||
https://github.com/mrshurik/poly_span
|
||||
|
||||
namespace span {
|
||||
Modifications:
|
||||
Copyright(c) 2022 John Wellbelove
|
||||
|
||||
/**
|
||||
* C++20 std::span-like view with focus on polymorphic aspect of types.
|
||||
* Provides a base class / interface view. Type can be const or non-const.
|
||||
* The class behaves like std::span, has O(1) index access and provides RandomAccess iterators.
|
||||
*
|
||||
* Hints:
|
||||
* 1. NEVER assign to elements or apply mutable algorithms to a mutable view to a base class. Object slicing!
|
||||
* 2. Pay attention to lifetime of the source buffer. poly_span should mostly be used as an argument of functions.
|
||||
* 3. The view has no data() for reason. Pointer to the first byte of the first object is unknown in general.
|
||||
*/
|
||||
template <typename Type>
|
||||
class poly_span {
|
||||
private:
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_POLY_SPAN_INCLUDED
|
||||
#define ETL_POLY_SPAN_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
#include "iterator.h"
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// The base class for poly_span exceptions.
|
||||
//***************************************************************************
|
||||
class poly_span_exception : public exception
|
||||
{
|
||||
public:
|
||||
|
||||
poly_span_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The out of range exceptions.
|
||||
//***************************************************************************
|
||||
class poly_span_out_of_range : public poly_span_exception
|
||||
{
|
||||
public:
|
||||
|
||||
poly_span_out_of_range(string_type file_name_, numeric_type line_number_)
|
||||
: poly_span_exception("poly_span:out of range", file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace private_poly_span
|
||||
{
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
using HasSize = etl::is_integral<decltype(etl::declval<TType&>().size())>;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
using DataType = decltype(etl::declval<TType&>().data());
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
using HasData = etl::is_pointer<DataType<TType>>;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TFrom, typename TType>
|
||||
using HasConvertibleData = etl::is_convertible<DataType<TFrom>, TType*>;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TFrom, typename TTo>
|
||||
using TransferConst = typename etl::conditional<etl::is_const<TFrom>::value,
|
||||
typename etl::add_const<TTo>::type,
|
||||
TTo>::type;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
class poly_span_iterator;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
struct IsPolySpanItImpl : etl::false_type {};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
struct IsPolySpanItImpl<poly_span_iterator<TType>> : etl::true_type {};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
using IsPolySpanIterator = IsPolySpanItImpl<TIterator>;
|
||||
|
||||
//***************************************************************************
|
||||
/// Iterator implementation
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
class poly_span_iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, TType>
|
||||
{
|
||||
private:
|
||||
|
||||
template <typename TOther>
|
||||
using EnableIfConversionToConst = etl::enable_if_t<etl::is_const<TType>::value && etl::is_same<TType, const TOther>::value>;
|
||||
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator() = default;
|
||||
poly_span_iterator(const poly_span_iterator&) = default;
|
||||
poly_span_iterator& operator=(const poly_span_iterator&) = default;
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator(TType* ptr, size_t element_size) noexcept
|
||||
: m_ptr(ptr), m_element_size(element_size)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TMutableType, typename = EnableIfConversionToConst<TMutableType>>
|
||||
poly_span_iterator(const poly_span_iterator<TMutableType>& other) noexcept
|
||||
: m_ptr(other.m_ptr)
|
||||
, m_element_size(other.m_element_size)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
TType* operator ->() const noexcept
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
TType& operator *() const noexcept
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator& operator ++() noexcept
|
||||
{
|
||||
from_char_ptr(to_char_ptr() + m_element_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator& operator --() noexcept
|
||||
{
|
||||
from_char_ptr(to_char_ptr() - m_element_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator& operator +=(ptrdiff_t n) noexcept
|
||||
{
|
||||
from_char_ptr(to_char_ptr() + (n * m_element_size));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend ptrdiff_t operator -(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return (left.to_char_ptr() - right.to_char_ptr()) / left.m_element_size;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator operator +(ptrdiff_t n) const noexcept
|
||||
{
|
||||
poly_span_iterator tmp = *this;
|
||||
tmp += n;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator operator ++(int) noexcept
|
||||
{
|
||||
poly_span_iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator operator --(int) noexcept
|
||||
{
|
||||
poly_span_iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator operator-(ptrdiff_t n) const noexcept
|
||||
{
|
||||
return *this + (-n);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
poly_span_iterator& operator-=(ptrdiff_t n) noexcept
|
||||
{
|
||||
return *this += -n;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
TType& operator[](ptrdiff_t n) const noexcept
|
||||
{
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend poly_span_iterator operator+(ptrdiff_t n, poly_span_iterator other) noexcept
|
||||
{
|
||||
return other + n;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator==(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr == right.m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator!=(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr != right.m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator >(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr > right.m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator <(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr < right.m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator>=(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr >= right.m_ptr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
friend bool operator<=(poly_span_iterator left, poly_span_iterator right) noexcept
|
||||
{
|
||||
return left.m_ptr <= right.m_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename>
|
||||
friend class poly_span_iterator;
|
||||
|
||||
using void_ptr_t = TransferConst<TType, void>*;
|
||||
using char_ptr_t = TransferConst<TType, char>*;
|
||||
|
||||
//***************************************************************************
|
||||
char_ptr_t to_char_ptr() const noexcept
|
||||
{
|
||||
return static_cast<char_ptr_t>(static_cast<void_ptr_t>(m_ptr));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
void from_char_ptr(char_ptr_t ptr) noexcept
|
||||
{
|
||||
m_ptr = static_cast<TType*>(static_cast<void_ptr_t>(ptr));
|
||||
}
|
||||
|
||||
TType* m_ptr;
|
||||
size_t m_element_size;
|
||||
};
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// C++11 etl::span-like view with focus on polymorphic aspect of types.
|
||||
/// Provides a base class / interface view. Type can be const or non-const.
|
||||
/// The class behaves like etl::span, has O(1) index access and provides RandomAccess iterators.
|
||||
/// Hints:
|
||||
/// 1. NEVER assign to elements or apply mutable algorithms to a mutable view to a base class. Object slicing!
|
||||
/// 2. Pay attention to lifetime of the source buffer. poly_span should mostly be used as an argument of functions.
|
||||
/// 3. The view has no data() for reason. Pointer to the first byte of the first object is unknown in general.
|
||||
//***************************************************************************
|
||||
template <typename TType>
|
||||
class poly_span
|
||||
{
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
template <typename Object>
|
||||
using EnableIfConvertibleFromObject = detail::enable_if_t<
|
||||
detail::HasSize<Object>::value && detail::HasData<Object>::value &&
|
||||
detail::HasConvertibleData<Object, Type>::value>;
|
||||
using EnableIfConvertibleFromObject = etl::enable_if_t<private_poly_span::HasSize<Object>::value &&
|
||||
private_poly_span::HasData<Object>::value &&
|
||||
private_poly_span::HasConvertibleData<Object, TType>::value>;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename OtherType>
|
||||
using EnableIfConvertibleType = detail::enable_if_t<
|
||||
std::is_convertible<OtherType*, Type*>::value>;
|
||||
using EnableIfTConvertibleType = etl::enable_if_t<etl::is_convertible<OtherType*, TType*>::value>;
|
||||
|
||||
//***************************************************************************
|
||||
template <typename Iterator>
|
||||
using IsContiguousIterator = std::integral_constant<bool,
|
||||
std::is_base_of<std::random_access_iterator_tag,
|
||||
typename std::iterator_traits<Iterator>::iterator_category>::value &&
|
||||
!detail::IsPolySpanIterator<Iterator>::value>;
|
||||
using IsTContiguousIterator = etl::integral_constant<bool,
|
||||
etl::is_base_of<ETL_OR_STD::random_access_iterator_tag, typename ETL_OR_STD::iterator_traits<Iterator>::iterator_category>::value// &&
|
||||
/*!private_poly_span::IsPolySpanIterator<Iterator>::value*/>;
|
||||
|
||||
public:
|
||||
using element_type = Type;
|
||||
using value_type = typename std::remove_cv<Type>::type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Type*;
|
||||
using reference = Type&;
|
||||
using const_pointer = const Type*;
|
||||
using const_reference = const Type&;
|
||||
using iterator = detail::poly_span_iterator<Type>;
|
||||
using const_iterator = detail::poly_span_iterator<const Type>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
public:
|
||||
|
||||
using element_type = TType;
|
||||
using value_type = typename etl::remove_cv<TType>::type;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = TType*;
|
||||
using reference = TType&;
|
||||
using const_pointer = const TType*;
|
||||
using const_reference = const TType&;
|
||||
using iterator = private_poly_span::poly_span_iterator<TType>;
|
||||
using const_iterator = private_poly_span::poly_span_iterator<const TType>;
|
||||
using reverse_iterator = etl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = etl::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr size_t npos = ~size_t(0);
|
||||
|
||||
/// Creates empty view.
|
||||
//***************************************************************************
|
||||
/// Default constructor
|
||||
//***************************************************************************
|
||||
poly_span() = default;
|
||||
|
||||
//***************************************************************************
|
||||
/// Copy constructor
|
||||
//***************************************************************************
|
||||
poly_span(const poly_span&) = default;
|
||||
|
||||
//***************************************************************************
|
||||
/// Assignment operator
|
||||
//***************************************************************************
|
||||
poly_span& operator=(const poly_span&) = default;
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from a compatible poly_span: convert mutable to const, derived to base type.
|
||||
template <typename ConvertibleType>
|
||||
poly_span(const poly_span<ConvertibleType>& span) noexcept
|
||||
: poly_span(span.m_dataPtr, span.m_size, span.m_element_size) {}
|
||||
|
||||
|
||||
/// Construct from a range of iterators or pointers. Iterators must Contiguous.
|
||||
template <typename ContiguousIterator>
|
||||
poly_span(ContiguousIterator begin, ContiguousIterator end) noexcept
|
||||
: poly_span(&*begin, end - begin, nullptr) {
|
||||
static_assert(IsContiguousIterator<ContiguousIterator>::value, "Wrong iterator");
|
||||
//***************************************************************************
|
||||
template <typename TConvertibleType>
|
||||
poly_span(const poly_span<TConvertibleType>& span) noexcept
|
||||
: poly_span(span.m_dataPtr, span.m_size, span.m_element_size)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from a range defined as iterator/pointer to begin and size. Iterators must Contiguous.
|
||||
template <typename ContiguousIterator>
|
||||
poly_span(ContiguousIterator begin, size_t size) noexcept
|
||||
: poly_span(&*begin, size, nullptr) {
|
||||
static_assert(IsContiguousIterator<ContiguousIterator>::value, "Wrong iterator");
|
||||
//***************************************************************************
|
||||
/// Construct from a range of iterators or pointers.
|
||||
/// Iterators must Contiguous.
|
||||
//***************************************************************************
|
||||
template <typename TContiguousIterator>
|
||||
poly_span(TContiguousIterator begin, TContiguousIterator end) noexcept
|
||||
: poly_span(&*begin, end - begin, ETL_NULLPTR)
|
||||
{
|
||||
static_assert(IsTContiguousIterator<TContiguousIterator>::value, "Not a contiguous iterator");
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from a range defined as iterator/pointer to begin and size.
|
||||
/// Iterators must Contiguous.
|
||||
//***************************************************************************
|
||||
template <typename TContiguousIterator>
|
||||
poly_span(TContiguousIterator begin, size_t size) noexcept
|
||||
: poly_span(&*begin, size, ETL_NULLPTR)
|
||||
{
|
||||
static_assert(IsTContiguousIterator<TContiguousIterator>::value, "Not a contiguous iterator");
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from a C-style array.
|
||||
template <typename ConvertibleType, size_t N>
|
||||
poly_span(ConvertibleType(&array)[N]) noexcept
|
||||
: poly_span(array, N, nullptr) {}
|
||||
//***************************************************************************
|
||||
template <typename TConvertibleType, size_t N>
|
||||
poly_span(TConvertibleType(&array)[N]) noexcept
|
||||
: poly_span(array, N, ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from initializer_list.
|
||||
template <typename ConvertibleType,
|
||||
typename = EnableIfConvertibleType<const ConvertibleType>>
|
||||
poly_span(std::initializer_list<ConvertibleType> list) noexcept
|
||||
: poly_span(list.begin(), list.size(), nullptr) {}
|
||||
//***************************************************************************
|
||||
/// Construct from a buffer objects: etl::vector, etl::array, etl::span or any class with data() and size().
|
||||
//***************************************************************************
|
||||
template <typename TBufferLikeObj, typename = EnableIfConvertibleFromObject<TBufferLikeObj>>
|
||||
poly_span(TBufferLikeObj& buffer) noexcept
|
||||
: poly_span(buffer.data()
|
||||
, buffer.size()
|
||||
, ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from a buffer objects: std::vector, std::array, std::span or any class with data() and size().
|
||||
template <typename BufferLikeObj,
|
||||
typename = EnableIfConvertibleFromObject<BufferLikeObj>>
|
||||
poly_span(BufferLikeObj& buffer) noexcept
|
||||
: poly_span(buffer.data(), buffer.size(), nullptr) {}
|
||||
//***************************************************************************
|
||||
/// Get the beginning of the span
|
||||
//***************************************************************************
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return { m_dataPtr, m_element_size };
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the end of the span
|
||||
//***************************************************************************
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return { element_at(m_size), m_element_size };
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the beginning of the span
|
||||
//***************************************************************************
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the end of the span
|
||||
//***************************************************************************
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the reverse beginning of the span
|
||||
//***************************************************************************
|
||||
reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
iterator begin() const noexcept { return {m_dataPtr, m_element_size}; }
|
||||
iterator end() const noexcept { return {elementAt(m_size), m_element_size}; }
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
|
||||
reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
|
||||
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
//***************************************************************************
|
||||
/// Get the end of the span
|
||||
//***************************************************************************
|
||||
reverse_iterator rend() const noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the reverse beginning of the span
|
||||
//***************************************************************************
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get the end of the span
|
||||
//***************************************************************************
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns true if the view has no elements.
|
||||
bool empty() const noexcept { return m_size == 0; }
|
||||
//***************************************************************************
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Number of elements in the view.
|
||||
size_t size() const noexcept { return m_size; }
|
||||
|
||||
/**
|
||||
* @brief sizeof(OriginalType) where OriginalType is type of the source buffer.
|
||||
* It's not sizeof(Type) for poly_span<Type>!
|
||||
*/
|
||||
size_t element_size() const noexcept { return m_element_size; }
|
||||
|
||||
/**
|
||||
* @brief Checks that other poly_span provides view to the same source buffer.
|
||||
* It's not like std::span operator==() which checks for elements equality.
|
||||
*/
|
||||
bool equal_view(const poly_span<const Type>& other) const noexcept {
|
||||
return (m_dataPtr == other.m_dataPtr) && (m_size == other.m_size)
|
||||
&& (m_element_size == other.m_element_size);
|
||||
//***************************************************************************
|
||||
size_t size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// \brief sizeof(OriginalType) where OriginalType is type of the source buffer.
|
||||
/// It's not sizeof(TType) for poly_span<TType>!
|
||||
//***************************************************************************
|
||||
size_t element_size() const noexcept
|
||||
{
|
||||
return m_element_size;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// \brief Checks that other poly_span provides view to the same source buffer.
|
||||
/// It's not like etl::span operator==() which checks for elements equality.
|
||||
//***************************************************************************
|
||||
bool equal_view(const poly_span<const TType>& other) const noexcept
|
||||
{
|
||||
return (m_dataPtr == other.m_dataPtr) &&
|
||||
(m_size == other.m_size) &&
|
||||
(m_element_size == other.m_element_size);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Reference to the element with given index. No out of bounds check.
|
||||
reference operator[](size_t index) const noexcept { return *elementAt(index); }
|
||||
|
||||
/**
|
||||
* @brief Index access with out of bounds checks.
|
||||
* @param index position of element in the view.
|
||||
* @throw std::out_of_range if index >= size().
|
||||
* @return reference to the element.
|
||||
*/
|
||||
reference at(size_t index) const {
|
||||
if (index >= m_size) throw std::out_of_range("at() ind >= size()");
|
||||
return *elementAt(index);
|
||||
//***************************************************************************
|
||||
reference operator[](size_t index) const noexcept
|
||||
{
|
||||
return *element_at(index);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// \brief Index access with out of bounds checks.
|
||||
/// \param index position of element in the view.
|
||||
/// Asserts etl::poly_span_out_of_range if index >= size().
|
||||
/// \return reference to the element.
|
||||
//***************************************************************************
|
||||
reference at(size_t index) const
|
||||
{
|
||||
ETL_ASSERT(index < m_size, ETL_ERROR(etl::poly_span_out_of_range));
|
||||
|
||||
return *element_at(index);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Reference to the first element. The view must be non-empty.
|
||||
reference front() const noexcept { return *m_dataPtr; }
|
||||
//***************************************************************************
|
||||
reference front() const noexcept
|
||||
{
|
||||
return *m_dataPtr;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Reference to the last element. The view must be non-empty.
|
||||
reference back() const noexcept { return *elementAt(m_size - 1); }
|
||||
|
||||
/**
|
||||
* @brief Creates a new view as a subrange of this.
|
||||
* @param pos Starting offset for the new view.
|
||||
* @param count Number of elements to take into the new view. Default npos is to take all until the end.
|
||||
* @throw std::out_of_range if pos > size().
|
||||
* @return New sub-view. If count > number of elements before the end it's the same as npos, no error.
|
||||
*/
|
||||
poly_span subspan(size_t pos, size_t count = npos) const {
|
||||
if (pos > m_size) throw std::out_of_range("subspan() pos > size()");
|
||||
return {elementAt(pos), minImpl(m_size - pos, count), m_element_size};
|
||||
//***************************************************************************
|
||||
reference back() const noexcept
|
||||
{
|
||||
return *element_at(m_size - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new view from exactly N first elements.
|
||||
* @param count Exact number of elements to take.
|
||||
* @throw std::out_of_range if count > size().
|
||||
* @return New sub-view.
|
||||
*/
|
||||
poly_span first(size_t count) const {
|
||||
if (count > m_size) throw std::out_of_range("first() count > size()");
|
||||
return {m_dataPtr, count, m_element_size};
|
||||
//***************************************************************************
|
||||
/// \brief Creates a new view as a subrange of this.
|
||||
/// \param pos Starting offset for the new view.
|
||||
/// \param count Number of elements to take into the new view. Default npos is to take all until the end.
|
||||
/// Asserts etl::poly_span_out_of_range if pos > size().
|
||||
/// \return New sub-view. If count > number of elements before the end it's the same as npos, no error.
|
||||
//***************************************************************************
|
||||
poly_span subspan(size_t pos, size_t count = npos) const
|
||||
{
|
||||
ETL_ASSERT(pos <= m_size, ETL_ERROR(etl::poly_span_out_of_range));
|
||||
|
||||
return { element_at(pos), min_impl(m_size - pos, count), m_element_size };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new view from exactly N last elements.
|
||||
* @param count Exact number of elements to take.
|
||||
* @throw std::out_of_range if count > size().
|
||||
* @return New sub-view.
|
||||
*/
|
||||
poly_span last(size_t count) const {
|
||||
if (count > m_size) throw std::out_of_range("last() count > size()");
|
||||
return {elementAt(m_size - count), count, m_element_size};
|
||||
//***************************************************************************
|
||||
/// \brief Creates a new view from exactly N first elements.
|
||||
/// \param count Exact number of elements to take.
|
||||
/// Asserts etl::poly_span_out_of_range if count > size().
|
||||
/// \return New sub-view.
|
||||
//***************************************************************************
|
||||
poly_span first(size_t count) const
|
||||
{
|
||||
ETL_ASSERT(count <= m_size, ETL_ERROR(etl::poly_span_out_of_range));
|
||||
|
||||
return { m_dataPtr, count, m_element_size };
|
||||
}
|
||||
|
||||
private:
|
||||
poly_span(Type* dataPtr, size_t size, size_t element_size) noexcept
|
||||
: m_dataPtr(dataPtr), m_size(size), m_element_size(element_size) {}
|
||||
//***************************************************************************
|
||||
/// \brief Creates a new view from exactly N last elements.
|
||||
/// \param count Exact number of elements to take.
|
||||
/// Asserts etl::poly_span_out_of_range if count > size().
|
||||
/// \return New sub-view.
|
||||
//***************************************************************************
|
||||
poly_span last(size_t count) const
|
||||
{
|
||||
ETL_ASSERT(count <= m_size, ETL_ERROR(etl::poly_span_out_of_range));
|
||||
|
||||
return { element_at(m_size - count), count, m_element_size };
|
||||
}
|
||||
|
||||
template <typename ConvertibleType>
|
||||
poly_span(ConvertibleType* dataPtr, size_t size, std::nullptr_t) noexcept
|
||||
: m_dataPtr(dataPtr), m_size(size), m_element_size(sizeof(ConvertibleType)) {}
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
poly_span(TType* dataPtr, size_t size, size_t element_size) noexcept
|
||||
: m_dataPtr(dataPtr)
|
||||
, m_size(size)
|
||||
, m_element_size(element_size)
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_STL
|
||||
//***************************************************************************
|
||||
template <typename TConvertibleType>
|
||||
poly_span(TConvertibleType* dataPtr, size_t size, std::nullptr_t) noexcept
|
||||
: m_dataPtr(dataPtr)
|
||||
, m_size(size)
|
||||
, m_element_size(sizeof(TConvertibleType))
|
||||
{
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
template <typename TConvertibleType>
|
||||
poly_span(TConvertibleType* dataPtr, size_t size, void*) noexcept
|
||||
: m_dataPtr(dataPtr)
|
||||
, m_size(size)
|
||||
, m_element_size(sizeof(TConvertibleType))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename>
|
||||
friend class poly_span;
|
||||
|
||||
using VoidPtr = detail::TransferConst<Type, void>*;
|
||||
using CharPtr = detail::TransferConst<Type, char>*;
|
||||
using void_ptr_t = private_poly_span::TransferConst<TType, void>*;
|
||||
using char_ptr_t = private_poly_span::TransferConst<TType, char>*;
|
||||
|
||||
Type* elementAt(size_t ind) const noexcept {
|
||||
const auto base = static_cast<CharPtr>(static_cast<VoidPtr>(m_dataPtr));
|
||||
return static_cast<Type*>(static_cast<VoidPtr>(base + ind * m_element_size));
|
||||
//***************************************************************************
|
||||
TType* element_at(size_t ind) const noexcept
|
||||
{
|
||||
const auto base = static_cast<char_ptr_t>(static_cast<void_ptr_t>(m_dataPtr));
|
||||
return static_cast<TType*>(static_cast<void_ptr_t>(base + (ind * m_element_size)));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
template <typename Value>
|
||||
static Value minImpl(Value a, Value b) noexcept { return (a < b) ? a : b; }
|
||||
static Value min_impl(Value a, Value b) noexcept
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
Type* m_dataPtr = nullptr;
|
||||
size_t m_size = 0;
|
||||
TType* m_dataPtr = ETL_NULLPTR;
|
||||
size_t m_size = 0;
|
||||
size_t m_element_size = 0;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,131 +4,10 @@
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace span {
|
||||
namespace detail {
|
||||
namespace private_poly_span
|
||||
{
|
||||
|
||||
template <bool Condition, typename Result = void>
|
||||
using enable_if_t = typename std::enable_if<Condition, Result>::type;
|
||||
|
||||
template <typename Type>
|
||||
using HasSize = std::is_integral<decltype(std::declval<Type&>().size())>;
|
||||
|
||||
template <typename Type>
|
||||
using DataType = decltype(std::declval<Type&>().data());
|
||||
|
||||
template <typename Type>
|
||||
using HasData = std::is_pointer<DataType<Type>>;
|
||||
|
||||
template <typename From, typename Type>
|
||||
using HasConvertibleData = std::is_convertible<DataType<From>, Type*>;
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
using TransferConst = typename std::conditional<std::is_const<FromType>::value,
|
||||
typename std::add_const<ToType>::type,
|
||||
ToType>::type;
|
||||
|
||||
template <typename Type>
|
||||
class poly_span_iterator;
|
||||
|
||||
template <typename Iter>
|
||||
struct IsPolySpanItImpl : std::false_type {};
|
||||
|
||||
template <typename Type>
|
||||
struct IsPolySpanItImpl<poly_span_iterator<Type>> : std::true_type {};
|
||||
|
||||
template <typename Iter>
|
||||
using IsPolySpanIterator = IsPolySpanItImpl<Iter>;
|
||||
|
||||
template <typename Type>
|
||||
class poly_span_iterator : public std::iterator<std::random_access_iterator_tag, Type> {
|
||||
private:
|
||||
template <typename Other>
|
||||
using EnableIfConversionToConst = enable_if_t<
|
||||
std::is_const<Type>::value && std::is_same<Type, const Other>::value>;
|
||||
|
||||
public:
|
||||
poly_span_iterator() = default;
|
||||
poly_span_iterator(const poly_span_iterator&) = default;
|
||||
poly_span_iterator& operator=(const poly_span_iterator&) = default;
|
||||
|
||||
poly_span_iterator(Type* ptr, size_t element_size) noexcept
|
||||
: m_ptr(ptr), m_element_size(element_size) {}
|
||||
|
||||
template <typename MutableType,
|
||||
typename = EnableIfConversionToConst<MutableType>>
|
||||
poly_span_iterator(const poly_span_iterator<MutableType>& other) noexcept
|
||||
: m_ptr(other.m_ptr), m_element_size(other.m_element_size) {}
|
||||
|
||||
Type* operator->() const noexcept { return m_ptr; }
|
||||
Type& operator*() const noexcept { return *m_ptr; }
|
||||
|
||||
friend bool operator==(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr == right.m_ptr; }
|
||||
friend bool operator!=(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr != right.m_ptr; }
|
||||
friend bool operator >(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr > right.m_ptr; }
|
||||
friend bool operator <(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr < right.m_ptr; }
|
||||
friend bool operator>=(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr >= right.m_ptr; }
|
||||
friend bool operator<=(poly_span_iterator left, poly_span_iterator right) noexcept { return left.m_ptr <= right.m_ptr; }
|
||||
|
||||
poly_span_iterator& operator++() noexcept {
|
||||
fromCharPtr(toCharPtr() + m_element_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
poly_span_iterator& operator--() noexcept {
|
||||
fromCharPtr(toCharPtr() - m_element_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
poly_span_iterator& operator+=(ptrdiff_t n) noexcept {
|
||||
fromCharPtr(toCharPtr() + n * m_element_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend ptrdiff_t operator-(poly_span_iterator left, poly_span_iterator right) noexcept {
|
||||
return (left.toCharPtr() - right.toCharPtr()) / left.m_element_size;
|
||||
}
|
||||
|
||||
poly_span_iterator operator+(ptrdiff_t n) const noexcept {
|
||||
poly_span_iterator tmp = *this;
|
||||
tmp += n;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
poly_span_iterator operator++(int) noexcept {
|
||||
poly_span_iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
poly_span_iterator operator--(int) noexcept {
|
||||
poly_span_iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
poly_span_iterator operator-(ptrdiff_t n) const noexcept { return *this + (-n); }
|
||||
|
||||
poly_span_iterator& operator-=(ptrdiff_t n) noexcept { return *this += -n; }
|
||||
|
||||
Type& operator[](ptrdiff_t n) const noexcept { return *(*this + n); }
|
||||
|
||||
friend poly_span_iterator operator+(ptrdiff_t n, poly_span_iterator other) noexcept {
|
||||
return other + n;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class poly_span_iterator;
|
||||
|
||||
using VoidPtr = TransferConst<Type, void>*;
|
||||
using CharPtr = TransferConst<Type, char>*;
|
||||
|
||||
CharPtr toCharPtr() const noexcept { return static_cast<CharPtr>(static_cast<VoidPtr>(m_ptr)); }
|
||||
void fromCharPtr(CharPtr ptr) noexcept { m_ptr = static_cast<Type*>(static_cast<VoidPtr>(ptr)); }
|
||||
|
||||
Type* m_ptr;
|
||||
size_t m_element_size;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,6 +213,7 @@ target_sources(t98 PRIVATE etl_profile.h
|
||||
../pearson.h.t.cpp
|
||||
../permutations.h.t.cpp
|
||||
../placement_new.h.t.cpp
|
||||
../poly_span.h.t.cpp
|
||||
../platform.h.t.cpp
|
||||
../pool.h.t.cpp
|
||||
../power.h.t.cpp
|
||||
|
||||
@ -214,6 +214,7 @@ target_sources(t11 PRIVATE etl_profile.h
|
||||
../permutations.h.t.cpp
|
||||
../placement_new.h.t.cpp
|
||||
../platform.h.t.cpp
|
||||
../poly_span.h.t.cpp
|
||||
../pool.h.t.cpp
|
||||
../power.h.t.cpp
|
||||
../priority_queue.h.t.cpp
|
||||
|
||||
@ -214,6 +214,7 @@ target_sources(t14 PRIVATE etl_profile.h
|
||||
../permutations.h.t.cpp
|
||||
../placement_new.h.t.cpp
|
||||
../platform.h.t.cpp
|
||||
../poly_span.h.t.cpp
|
||||
../pool.h.t.cpp
|
||||
../power.h.t.cpp
|
||||
../priority_queue.h.t.cpp
|
||||
|
||||
@ -214,6 +214,7 @@ target_sources(t17 PRIVATE etl_profile.h
|
||||
../permutations.h.t.cpp
|
||||
../placement_new.h.t.cpp
|
||||
../platform.h.t.cpp
|
||||
../poly_span.h.t.cpp
|
||||
../pool.h.t.cpp
|
||||
../power.h.t.cpp
|
||||
../priority_queue.h.t.cpp
|
||||
|
||||
29
test/sanity-check/poly_span.h.t.cpp
Normal file
29
test/sanity-check/poly_span.h.t.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2021 Bo Rydberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <etl/poly_span.h>
|
||||
365
test/test_poly_span.cpp
Normal file
365
test/test_poly_span.cpp
Normal file
@ -0,0 +1,365 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/poly_span.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
//***************************************************************************
|
||||
struct Base
|
||||
{
|
||||
virtual int value() const = 0;
|
||||
|
||||
virtual bool operator==(const Base& o) const { return value() == o.value(); }
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
struct Derived : Base
|
||||
{
|
||||
Derived(int v) : m_value(v) {}
|
||||
|
||||
int value() const override { return m_value; }
|
||||
|
||||
int m_value;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
struct AnotherBase
|
||||
{
|
||||
virtual double another_value() const { return v; };
|
||||
|
||||
double v = 0;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
struct MultiDerived : AnotherBase, Base
|
||||
{
|
||||
MultiDerived(int v) : m_value(v) {}
|
||||
|
||||
int value() const override { return m_value; }
|
||||
|
||||
int m_value;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename TSpan, typename TSource>
|
||||
bool equal(const TSpan& span, TSource& source)
|
||||
{
|
||||
auto sb = std::begin(source);
|
||||
return (span.size() == (std::end(source) - sb)) && std::equal(span.begin(), span.end(), sb);
|
||||
}
|
||||
|
||||
SUITE(test_poly_span)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_defaultConstruct)
|
||||
{
|
||||
etl::poly_span<Base> s{};
|
||||
CHECK(s.empty());
|
||||
CHECK_EQUAL(0, s.size());
|
||||
CHECK(s.begin() == s.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromVec)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3 };
|
||||
|
||||
etl::poly_span<int> s = v;
|
||||
CHECK_EQUAL(s[0], v[0]);
|
||||
CHECK_EQUAL(s[1], v[1]);
|
||||
CHECK_EQUAL(s[2], v[2]);
|
||||
CHECK_EQUAL(v.size(), s.size());
|
||||
CHECK_EQUAL(sizeof(v[0]), s.element_size());
|
||||
CHECK(!s.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromVecRespectConst)
|
||||
{
|
||||
std::vector<Derived> v;
|
||||
const auto& cv = v;
|
||||
etl::poly_span<const Base> s1 = v;
|
||||
etl::poly_span<const Base>{v};
|
||||
etl::poly_span<const Base> s2 = cv;
|
||||
etl::poly_span<const Base>{cv};
|
||||
etl::poly_span<Derived> s3 = v;
|
||||
etl::poly_span<Base>{v};
|
||||
// The line below shouldn't work if uncommented
|
||||
// etl::poly_span<int>{cv};
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromCArray)
|
||||
{
|
||||
int a[] = { 1, 2, 3 };
|
||||
etl::poly_span<const int> s = a;
|
||||
CHECK_EQUAL(s[0], a[0]);
|
||||
CHECK_EQUAL(s[1], a[1]);
|
||||
CHECK_EQUAL(s[2], a[2]);
|
||||
CHECK_EQUAL(3, s.size());
|
||||
CHECK_EQUAL(sizeof(a[0]), s.element_size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromCArrayRespectConst)
|
||||
{
|
||||
Derived ar[2] = { 1, 2 };
|
||||
const auto& car = ar;
|
||||
etl::poly_span<const Base> s1 = ar;
|
||||
etl::poly_span<const Base>{ar};
|
||||
etl::poly_span<const Derived> s2 = car;
|
||||
etl::poly_span<const Derived>{car};
|
||||
etl::poly_span<Base> s3 = ar;
|
||||
etl::poly_span<Base>{ar};
|
||||
// The line below shouldn't work if uncommented
|
||||
// etl::poly_span<int>{car};
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromArray)
|
||||
{
|
||||
std::array<int, 3> a = { 1, 2, 3 };
|
||||
|
||||
etl::poly_span<int> s = a;
|
||||
CHECK_EQUAL(s[0], a[0]);
|
||||
CHECK_EQUAL(s[1], a[1]);
|
||||
CHECK_EQUAL(s[2], a[2]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromPolySpan)
|
||||
{
|
||||
std::array<Derived, 3> a = { 1, 2, 3 };
|
||||
etl::poly_span<Derived> s1 = a;
|
||||
etl::poly_span<Base> s2 = s1;
|
||||
etl::poly_span<const Base>{s2};
|
||||
CHECK(equal(s1, s2));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromIterator)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3, 4 };
|
||||
|
||||
etl::poly_span<int> s1{ v.begin() + 1, v.end() };
|
||||
CHECK_EQUAL(v.size() - 1, s1.size());
|
||||
CHECK_EQUAL(s1[0], v[1]);
|
||||
CHECK_EQUAL(s1[1], v[2]);
|
||||
CHECK_EQUAL(s1[2], v[3]);
|
||||
|
||||
etl::poly_span<const int> s2{ v.data() + 1, v.data() + v.size() };
|
||||
CHECK(equal(s1, s2));
|
||||
|
||||
etl::poly_span<const int> s3{ v.cbegin(), v.size() };
|
||||
CHECK(equal(s3, v));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_constructFromInitializerList)
|
||||
{
|
||||
const int data[] = { 1, 2, 3, 4, 5 };
|
||||
etl::poly_span<const int> s(data);
|
||||
|
||||
CHECK_EQUAL(5, s.size());
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
//int x = s[i];
|
||||
//CHECK_EQUAL(i + 1, s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_DerivedToBase)
|
||||
{
|
||||
std::vector<Derived> v1 = { 0, 1, 2 };
|
||||
|
||||
Derived a1[] = { 0, 1, 2 };
|
||||
CHECK(sizeof(Derived) > sizeof(Base));
|
||||
|
||||
etl::poly_span<const Base> s1 = v1;
|
||||
CHECK_EQUAL(sizeof(Derived), s1.element_size());
|
||||
etl::poly_span<Base> s2 = a1;
|
||||
|
||||
auto it1 = s1.begin();
|
||||
auto it2 = s2.begin();
|
||||
|
||||
for (int i = 0; i < 3; ++i, ++it1, ++it2)
|
||||
{
|
||||
CHECK_EQUAL(i, s1[i].value());
|
||||
CHECK_EQUAL(i, s2[i].value());
|
||||
CHECK_EQUAL(i, it1->value());
|
||||
CHECK_EQUAL(i, it2->value());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_MultiDerivedToBase)
|
||||
{
|
||||
std::vector<MultiDerived> v1 = { 0, 1, 2 };
|
||||
|
||||
etl::poly_span<Base> s1 = v1;
|
||||
CHECK(static_cast<void*>(v1.data()) != static_cast<void*>(&s1.front()));
|
||||
CHECK(equal(s1, v1));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_typeProperties)
|
||||
{
|
||||
CHECK(std::is_trivial<etl::poly_span<int>::iterator>::value);
|
||||
CHECK(std::is_trivial<etl::poly_span<const Base>::iterator>::value);
|
||||
CHECK(std::is_trivial<etl::poly_span<int>::const_iterator>::value);
|
||||
CHECK(bool(std::is_base_of<ETL_OR_STD::random_access_iterator_tag, etl::poly_span<int>::iterator::iterator_category>::value));
|
||||
CHECK(std::is_trivially_copy_constructible<etl::poly_span<int>>::value);
|
||||
CHECK(std::is_trivially_copy_assignable<etl::poly_span<int>>::value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
//TEST(test_poly_span_iterators)
|
||||
//{
|
||||
// std::vector<int> v = { 1, 2, 3 };
|
||||
// etl::poly_span<int> s = v;
|
||||
// using iterator = etl::poly_span<int>::iterator;
|
||||
//
|
||||
// CHECK_EQUAL(s.end() - s.begin(), s.size());
|
||||
// CHECK_EQUAL(s.rend() - s.rbegin(), s.size());
|
||||
//
|
||||
// iterator b = s.begin();
|
||||
// CHECK(b + s.size() == s.end());
|
||||
// CHECK_EQUAL(b[0], 1);
|
||||
// CHECK(b < s.end());
|
||||
// CHECK(b != s.end());
|
||||
// CHECK(b + 2 > s.end() - 1);
|
||||
|
||||
// etl::poly_span<int>::const_iterator bc = b;
|
||||
// CHECK(bc <= s.end());
|
||||
// CHECK_EQUAL(s.back(), *s.crbegin());
|
||||
// CHECK_EQUAL(s.front(), s.crend()[-1]);
|
||||
//
|
||||
// bc += 1;
|
||||
// bc -= 1;
|
||||
// CHECK(bc == s.cbegin());
|
||||
// CHECK(std::is_sorted(s.cbegin(), s.cend()));
|
||||
//}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_randomAccessIteratorUse)
|
||||
{
|
||||
int data[] = { 25, 4, 3, -2, 1 };
|
||||
etl::poly_span<int> s = data;
|
||||
|
||||
std::sort(s.begin(), s.end());
|
||||
CHECK(std::is_sorted(std::begin(data), std::end(data)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_subspan)
|
||||
{
|
||||
const int data[] = { 1, 2, 3, 4, 5 };
|
||||
etl::poly_span<const int> s(data);
|
||||
|
||||
auto s1 = s.subspan(1, 2);
|
||||
CHECK_EQUAL(2, s1.size());
|
||||
CHECK_EQUAL(s[1], s1[0]);
|
||||
CHECK_EQUAL(s[2], s1[1]);
|
||||
|
||||
auto s2 = s.subspan(2);
|
||||
CHECK_EQUAL(3, s2.size());
|
||||
CHECK_EQUAL(s[2], s2[0]);
|
||||
CHECK_EQUAL(s[4], s2[2]);
|
||||
|
||||
auto s3 = s.subspan(0, 10);
|
||||
CHECK_EQUAL(s.size(), s3.size());
|
||||
CHECK_THROW(s.subspan(6, 1), etl::poly_span_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_first)
|
||||
{
|
||||
const int data[] = { 1, 2, 3, 4, 5 };
|
||||
etl::poly_span<const int> s(data);
|
||||
|
||||
CHECK_THROW(s.first(6), etl::poly_span_out_of_range);
|
||||
CHECK_EQUAL(s.first(5).size(), 5);
|
||||
CHECK(s.first(0).empty());
|
||||
|
||||
auto s1 = s.first(3);
|
||||
CHECK_EQUAL(3, s1.size());
|
||||
CHECK_EQUAL(1, s1[0]);
|
||||
CHECK_EQUAL(3, s1[2]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_last)
|
||||
{
|
||||
const int data[] = { 1, 2, 3, 4, 5 };
|
||||
etl::poly_span<const int> s(data);
|
||||
|
||||
CHECK_THROW(s.last(6), etl::poly_span_out_of_range);
|
||||
CHECK_EQUAL(s.last(5).size(), 5);
|
||||
|
||||
auto s2 = s.last(2);
|
||||
CHECK_EQUAL(2, s2.size());
|
||||
CHECK_EQUAL(4, s2[0]);
|
||||
CHECK_EQUAL(5, s2[1]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_equal_view)
|
||||
{
|
||||
std::vector<double> v = { 1.0, 2.0, 3.0 };
|
||||
etl::poly_span<double> s1 = v;
|
||||
etl::poly_span<const double> cs2 = v;
|
||||
|
||||
CHECK(!etl::poly_span<const double>{}.equal_view(s1));
|
||||
CHECK(s1.equal_view(cs2));
|
||||
CHECK(s1.last(2).equal_view(cs2.subspan(1)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_poly_span_at)
|
||||
{
|
||||
const int data[] = { 1, 2, 3 };
|
||||
etl::poly_span<const int> s(data);
|
||||
|
||||
CHECK_EQUAL(s.at(0), 1);
|
||||
CHECK_EQUAL(s.at(2), 3);
|
||||
CHECK_THROW(s.at(3), etl::poly_span_out_of_range);
|
||||
CHECK_THROW(s.at(-1), etl::poly_span_out_of_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2411,6 +2411,7 @@
|
||||
<ClInclude Include="..\..\include\etl\crc8_maxim.h" />
|
||||
<ClInclude Include="..\..\include\etl\crc8_rohc.h" />
|
||||
<ClInclude Include="..\..\include\etl\crc8_wcdma.h" />
|
||||
<ClInclude Include="..\..\include\etl\poly_span.h" />
|
||||
<ClInclude Include="..\..\include\etl\pseudo_moving_average.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate_service.h" />
|
||||
@ -5312,6 +5313,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='MSVC Debug - Appveyor|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug64|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\sanity-check\poly_span.h.t.cpp" />
|
||||
<ClCompile Include="..\sanity-check\pseudo_moving_average.h.t.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No STL - Built-ins|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No STL - Force Built-ins|Win32'">true</ExcludedFromBuild>
|
||||
@ -10973,6 +10975,7 @@
|
||||
<ClCompile Include="..\test_crc8_maxim.cpp" />
|
||||
<ClCompile Include="..\test_crc8_rohc.cpp" />
|
||||
<ClCompile Include="..\test_crc8_wcdma.cpp" />
|
||||
<ClCompile Include="..\test_poly_span.cpp" />
|
||||
<ClCompile Include="..\test_pseudo_moving_average.cpp" />
|
||||
<ClCompile Include="..\test_delegate.cpp" />
|
||||
<ClCompile Include="..\test_delegate_cpp03.cpp" />
|
||||
|
||||
@ -1281,6 +1281,9 @@
|
||||
<ClInclude Include="..\..\include\etl\generators\message_router_generator.h">
|
||||
<Filter>ETL\Messaging\Generators</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\poly_span.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test_string_char.cpp">
|
||||
@ -3260,6 +3263,12 @@
|
||||
<ClCompile Include="..\test_bit_stream_reader_little_endian.cpp">
|
||||
<Filter>Tests\Binary</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\sanity-check\poly_span.h.t.cpp">
|
||||
<Filter>Tests\Sanity Checks\Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_poly_span.cpp">
|
||||
<Filter>Tests\Containers</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user