Merge branch 'master' of https://github.com/Microsoft/GSL
Conflicts:
include/array_view.h
diff --git a/include/array_view.h b/include/array_view.h
index c884c11..4211637 100644
--- a/include/array_view.h
+++ b/include/array_view.h
@@ -68,12 +68,6 @@
*/
namespace details
{
- template <typename SizeType>
- struct SizeTypeTraits
- {
- static const SizeType max_value = std::is_signed<SizeType>::value ? static_cast<typename std::make_unsigned<SizeType>::type>(-1) / 2 : static_cast<SizeType>(-1);
- };
-
template <typename T>
class arrow_proxy
{
@@ -94,13 +88,12 @@
};
}
-template <size_t Rank, typename ValueType = size_t>
+template <size_t Rank>
class index final
{
- static_assert(std::is_integral<ValueType>::value, "ValueType must be an integral type!");
static_assert(Rank > 0, "Rank must be greater than 0!");
- template <size_t OtherRank, typename OtherValueType>
+ template <size_t OtherRank>
friend class index;
public:
@@ -248,18 +241,35 @@
value_type elems[Rank] = {};
};
-template <typename ValueType>
-class index<1, ValueType>
+template<>
+class index<1>
{
+public:
+ static const size_t rank = 1;
+ using size_type = std::ptrdiff_t;
+ using value_type = std::ptrdiff_t;
+ using reference = std::add_lvalue_reference_t<std::ptrdiff_t>;
+ using const_reference = const std::ptrdiff_t&;//std::add_const_t<std::add_lvalue_reference_t<std::ptrdiff_t>>;
+
+ constexpr index() noexcept : value(0)
+ {}
+
+ constexpr index(value_type e0) noexcept : value(e0)
+ {}
+
+ constexpr index(const value_type(&values)[1]) noexcept : index(values[0])
+ {}
+
+ // Preconditions: il.size() == rank
+ constexpr index(std::initializer_list<value_type> il)
+ {
+ fail_fast_assert(il.size() == rank, "Size of the initializer list must match the rank of the array");
+ value = begin(il)[0];
+ }
+
template <size_t, typename OtherValueType>
friend class index;
-public:
- static const size_t rank = 1;
- using value_type = std::remove_reference_t<ValueType>;
- using reference = std::add_lvalue_reference_t<value_type>;
- using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;
-
constexpr index() noexcept : value(0)
{}
@@ -271,294 +281,234 @@
constexpr index(const index &) noexcept = default;
- template <typename OtherValueType,
- bool Enabled = (details::SizeTypeTraits<OtherValueType>::max_value <= details::SizeTypeTraits<value_type>::max_value),
- typename Other = std::enable_if_t<Enabled, index<1, OtherValueType>>>
- constexpr index(const index<1, OtherValueType>& other) noexcept
- {
- value = static_cast<ValueType>(other.value);
- }
-
- template <typename OtherValueType,
- bool Enabled = (details::SizeTypeTraits<OtherValueType>::max_value > details::SizeTypeTraits<value_type>::max_value),
- typename Other = std::enable_if_t<Enabled, index<1, OtherValueType>>>
- constexpr index(const index<1, OtherValueType>& other, void* ptr=0) noexcept
- {
- fail_fast_assert(other.value <= static_cast<OtherValueType>(details::SizeTypeTraits<value_type>::max_value));
- value = static_cast<value_type>(other.value);
- }
-
- // Preconditions: component_idx < 1
- constexpr reference operator[](value_type component_idx) noexcept
+ // Preconditions: component_idx < rank
+ constexpr reference operator[](size_type component_idx) noexcept
{
fail_fast_assert(component_idx == 0, "Component index must be less than rank");
- (void)(component_idx);
return value;
}
- // Preconditions: component_idx < 1
- constexpr const_reference operator[](value_type component_idx) const noexcept
+
+ // Preconditions: component_idx < rank
+ constexpr const_reference operator[](size_type component_idx) const noexcept
{
fail_fast_assert(component_idx == 0, "Component index must be less than rank");
- (void)(component_idx);
return value;
}
+
constexpr bool operator==(const index& rhs) const noexcept
{
return value == rhs.value;
}
+
constexpr bool operator!=(const index& rhs) const noexcept
{
return !(*this == rhs);
}
- constexpr index operator+() const noexcept
+
+ constexpr index operator+() const noexcept
{
return *this;
}
- constexpr index operator-() const noexcept
+
+ constexpr index operator-() const noexcept
{
return index(-value);
}
- constexpr index operator+(const index& rhs) const noexcept
+
+ constexpr index operator+(const index& rhs) const noexcept
{
return index(value + rhs.value);
}
- constexpr index operator-(const index& rhs) const noexcept
+
+ constexpr index operator-(const index& rhs) const noexcept
{
return index(value - rhs.value);
}
- constexpr index& operator+=(const index& rhs) noexcept
+
+ constexpr index& operator+=(const index& rhs) noexcept
{
value += rhs.value;
return *this;
}
- constexpr index& operator-=(const index& rhs) noexcept
+
+ constexpr index& operator-=(const index& rhs) noexcept
{
value -= rhs.value;
return *this;
}
- constexpr index& operator++() noexcept
+
+ constexpr index& operator++() noexcept
{
++value;
return *this;
}
- constexpr index operator++(int) noexcept
+
+ constexpr index operator++(int) noexcept
{
index ret = *this;
++(*this);
return ret;
}
- constexpr index& operator--() noexcept
+
+ constexpr index& operator--() noexcept
{
--value;
return *this;
}
- constexpr index operator--(int) noexcept
+
+ constexpr index operator--(int) noexcept
{
index ret = *this;
--(*this);
return ret;
}
- constexpr index operator*(value_type v) const noexcept
+
+ constexpr index operator*(value_type v) const noexcept
{
return index(value * v);
}
- constexpr index operator/(value_type v) const noexcept
+
+ constexpr index operator/(value_type v) const noexcept
{
return index(value / v);
}
- constexpr index& operator*=(value_type v) noexcept
+
+ constexpr index& operator*=(value_type v) noexcept
{
value *= v;
return *this;
}
- constexpr index& operator/=(value_type v) noexcept
+
+ constexpr index& operator/=(value_type v) noexcept
{
value /= v;
return *this;
}
- friend constexpr index operator*(value_type v, const index& rhs) noexcept
+
+ friend constexpr index operator*(value_type v, const index& rhs) noexcept
{
return{ rhs * v };
}
+
private:
value_type value;
};
-#ifndef _MSC_VER
-
-struct static_bounds_dynamic_range_t
-{
- template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
- constexpr operator T() const noexcept
- {
- return static_cast<T>(-1);
- }
-
- template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
- constexpr bool operator ==(T other) const noexcept
- {
- return static_cast<T>(-1) == other;
- }
-
- template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
- constexpr bool operator !=(T other) const noexcept
- {
- return static_cast<T>(-1) != other;
- }
-
-};
-
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator ==(T left, static_bounds_dynamic_range_t right) noexcept
-{
- return right == left;
-}
-
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator !=(T left, static_bounds_dynamic_range_t right) noexcept
-{
- return right != left;
-}
-
-constexpr static_bounds_dynamic_range_t dynamic_range{};
-#else
-const char dynamic_range = -1;
-#endif
+const std::ptrdiff_t dynamic_range = -1;
struct generalized_mapping_tag {};
struct contiguous_mapping_tag : generalized_mapping_tag {};
namespace details
{
- template <typename SizeType, SizeType Fact1, SizeType Fact2, SizeType ConstBound>
- struct StaticSizeHelperImpl
- {
- static_assert(static_cast<size_t>(Fact1) * static_cast<size_t>(Fact2) <= SizeTypeTraits<SizeType>::max_value, "Value out of the range of SizeType");
- static const SizeType value = Fact1 * Fact2;
- };
- template <typename SizeType, SizeType Fact1, SizeType ConstBound>
- struct StaticSizeHelperImpl<SizeType, Fact1, ConstBound, ConstBound>
- {
- static const SizeType value = ConstBound;
- };
-
- template <typename SizeType, SizeType Fact2, SizeType ConstBound>
- struct StaticSizeHelperImpl<SizeType, ConstBound, Fact2, ConstBound>
- {
- static const SizeType value = ConstBound;
- };
-
- template <typename SizeType, SizeType ConstBound>
- struct StaticSizeHelperImpl<SizeType, ConstBound, ConstBound, ConstBound>
- {
- static const SizeType value = static_cast<SizeType>(ConstBound);
- };
-
- template <typename SizeType, SizeType Fact1, SizeType Fact2>
- struct StaticSizeHelper
- {
- static const SizeType value = StaticSizeHelperImpl<SizeType, static_cast<SizeType>(Fact1), static_cast<SizeType>(Fact2), static_cast<SizeType>(dynamic_range)>::value;
- };
-
-
- template <size_t Left, size_t Right>
+ template <std::ptrdiff_t Left, std::ptrdiff_t Right>
struct LessThan
{
static const bool value = Left < Right;
};
- template <typename SizeType, size_t... Ranges>
+ template <std::ptrdiff_t... Ranges>
struct BoundsRanges {
- static const size_t Depth = 0;
- static const size_t DynamicNum = 0;
- static const SizeType CurrentRange = 1;
- static const SizeType TotalSize = 1;
+ using size_type = std::ptrdiff_t;
+ static const size_type Depth = 0;
+ static const size_type DynamicNum = 0;
+ static const size_type CurrentRange = 1;
+ static const size_type TotalSize = 1;
- BoundsRanges (const BoundsRanges &) = default;
-
- // TODO : following signature is for work around VS bug
- template <typename OtherType>
- BoundsRanges (const OtherType &, bool /* firstLevel */) {}
- BoundsRanges(const SizeType * const) { }
+ BoundsRanges (const BoundsRanges&) = default;
+ BoundsRanges(const size_type* const) { }
BoundsRanges() = default;
template <typename T, size_t Dim>
- void serialize(T &) const {
- }
+ void serialize(T&) const
+ {}
+
template <typename T, size_t Dim>
- SizeType linearize(const T &) const {
- return 0;
- }
- template <typename T, size_t Dim>
- ptrdiff_t contains(const T &) const {
+ size_type linearize(const T&) const
+ {
return 0;
}
- size_t totalSize() const noexcept {
+ template <typename T, size_t Dim>
+ bool contains(const T&) const
+ {
+ return 0;
+ }
+
+ size_type totalSize() const noexcept
+ {
return TotalSize;
}
- bool operator == (const BoundsRanges &) const noexcept
+ bool operator==(const BoundsRanges&) const noexcept
{
return true;
}
};
- template <typename SizeType, size_t... RestRanges>
- struct BoundsRanges <SizeType, dynamic_range, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{
- using Base = BoundsRanges <SizeType, RestRanges... >;
+ template <std::ptrdiff_t... RestRanges>
+ struct BoundsRanges <dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>{
+ using Base = BoundsRanges <RestRanges... >;
+ using size_type = Base::size_type;
static const size_t Depth = Base::Depth + 1;
static const size_t DynamicNum = Base::DynamicNum + 1;
- static const SizeType CurrentRange = dynamic_range;
- static const SizeType TotalSize = dynamic_range;
- const SizeType m_bound;
+ static const size_type CurrentRange = dynamic_range;
+ static const size_type TotalSize = dynamic_range;
+ const size_type m_bound;
- BoundsRanges (const BoundsRanges &) = default;
- BoundsRanges(const SizeType * const arr) : Base(arr + 1), m_bound(static_cast<SizeType>(*arr * this->Base::totalSize()))
+ BoundsRanges (const BoundsRanges&) = default;
+
+ BoundsRanges(const size_type* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
{
fail_fast_assert(0 <= *arr);
- fail_fast_assert(*arr * this->Base::totalSize() <= details::SizeTypeTraits<SizeType>::max_value);
}
+
BoundsRanges() : m_bound(0) {}
- template <typename OtherSizeType, size_t OtherRange, size_t... RestOtherRanges>
- BoundsRanges(const BoundsRanges<OtherSizeType, OtherRange, RestOtherRanges...> &other, bool /* firstLevel */ = true) :
- Base(static_cast<const BoundsRanges<OtherSizeType, RestOtherRanges...>&>(other), false), m_bound (static_cast<SizeType>(other.totalSize()))
- {
- }
+ template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
+ BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>& other, bool /* firstLevel */ = true) :
+ Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false), m_bound(other.totalSize())
+ {}
template <typename T, size_t Dim = 0>
- void serialize(T & arr) const {
+ void serialize(T& arr) const
+ {
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
}
+
template <typename T, size_t Dim = 0>
- SizeType linearize(const T & arr) const {
- const size_t index = this->Base::totalSize() * arr[Dim];
- fail_fast_assert(index < static_cast<size_t>(m_bound));
- return static_cast<SizeType>(index) + this->Base::template linearize<T, Dim + 1>(arr);
+ size_type linearize(const T& arr) const
+ {
+ const size_type index = this->Base::totalSize() * arr[Dim];
+ fail_fast_assert(index < m_bound);
+ return index + this->Base::template linearize<T, Dim + 1>(arr);
}
template <typename T, size_t Dim = 0>
- ptrdiff_t contains(const T & arr) const {
+ size_type contains(const T & arr) const
+ {
const ptrdiff_t last = this->Base::template contains<T, Dim + 1>(arr);
if (last == -1)
return -1;
const ptrdiff_t cur = this->Base::totalSize() * arr[Dim];
- return static_cast<size_t>(cur) < static_cast<size_t>(m_bound) ? cur + last : -1;
+ return cur < m_bound ? cur + last : -1;
}
- size_t totalSize() const noexcept {
+ size_type totalSize() const noexcept
+ {
return m_bound;
}
- SizeType elementNum() const noexcept {
- return static_cast<SizeType>(totalSize() / this->Base::totalSize());
+ size_type elementNum() const noexcept
+ {
+ return totalSize() / this->Base::totalSize();
}
- SizeType elementNum(size_t dim) const noexcept{
+ size_type elementNum(size_t dim) const noexcept
+ {
if (dim > 0)
return this->Base::elementNum(dim - 1);
else
@@ -567,67 +517,75 @@
bool operator == (const BoundsRanges & rhs) const noexcept
{
- return m_bound == rhs.m_bound && static_cast<const Base &>(*this) == static_cast<const Base &>(rhs);
+ return m_bound == rhs.m_bound && static_cast<const Base&>(*this) == static_cast<const Base&>(rhs);
}
};
- template <typename SizeType, size_t CurRange, size_t... RestRanges>
- struct BoundsRanges <SizeType, CurRange, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{
- using Base = BoundsRanges <SizeType, RestRanges... >;
+ template <std::ptrdiff_t CurRange, std::ptrdiff_t... RestRanges>
+ struct BoundsRanges <CurRange, RestRanges...> : BoundsRanges<RestRanges...>
+ {
+ using Base = BoundsRanges <RestRanges... >;
+ using size_type = Base::size_type;
static const size_t Depth = Base::Depth + 1;
static const size_t DynamicNum = Base::DynamicNum;
- static const SizeType CurrentRange = static_cast<SizeType>(CurRange);
- static const SizeType TotalSize = StaticSizeHelper<SizeType, Base::TotalSize, CurrentRange>::value;
- static_assert (CurRange <= SizeTypeTraits<SizeType>::max_value, "CurRange must be smaller than SizeType limits");
+ static const size_type CurrentRange = CurRange;
+ static const size_type TotalSize = CurrentRange;
+ static_assert (CurRange <= PTRDIFF_MAX, "CurRange must be smaller than std::ptrdiff_t limits");
- BoundsRanges (const BoundsRanges &) = default;
- BoundsRanges(const SizeType * const arr) : Base(arr) { }
+ BoundsRanges (const BoundsRanges&) = default;
+ BoundsRanges(const size_type* const arr) : Base(arr) { }
BoundsRanges() = default;
- template <typename OtherSizeType, size_t OtherRange, size_t... RestOtherRanges>
- BoundsRanges(const BoundsRanges<OtherSizeType, OtherRange, RestOtherRanges...> &other, bool firstLevel = true) : Base(static_cast<const BoundsRanges<OtherSizeType, RestOtherRanges...>&>(other), false)
+ template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
+ BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>&other, bool firstLevel = true) : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
{
fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize());
}
template <typename T, size_t Dim = 0>
- void serialize(T & arr) const {
+ void serialize(T& arr) const
+ {
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
}
template <typename T, size_t Dim = 0>
- SizeType linearize(const T & arr) const {
+ size_type linearize(const T& arr) const
+ {
fail_fast_assert(arr[Dim] < CurrentRange, "Index is out of range");
- return static_cast<SizeType>(this->Base::totalSize()) * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr);
+ return this->Base::totalSize() * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr);
}
template <typename T, size_t Dim = 0>
- ptrdiff_t contains(const T & arr) const {
- if (static_cast<size_t>(arr[Dim]) >= CurrentRange)
+ size_type contains(const T& arr) const
+ {
+ if (arr[Dim] >= CurrentRange)
return -1;
- const ptrdiff_t last = this->Base::template contains<T, Dim + 1>(arr);
+ const size_type last = this->Base::template contains<T, Dim + 1>(arr);
if (last == -1)
return -1;
- return static_cast<ptrdiff_t>(this->Base::totalSize() * arr[Dim]) + last;
+ return this->Base::totalSize() * arr[Dim] + last;
}
- size_t totalSize() const noexcept{
+ size_type totalSize() const noexcept
+ {
return CurrentRange * this->Base::totalSize();
}
- SizeType elementNum() const noexcept{
+ size_type elementNum() const noexcept
+ {
return CurrentRange;
}
- SizeType elementNum(size_t dim) const noexcept{
+ size_type elementNum(size_t dim) const noexcept
+ {
if (dim > 0)
return this->Base::elementNum(dim - 1);
else
return elementNum();
}
- bool operator == (const BoundsRanges & rhs) const noexcept
+ bool operator== (const BoundsRanges& rhs) const noexcept
{
return static_cast<const Base &>(*this) == static_cast<const Base &>(rhs);
}
@@ -636,7 +594,6 @@
template <typename SourceType, typename TargetType, size_t Rank>
struct BoundsRangeConvertible2;
- // TODO: I have to rewrite BoundsRangeConvertible into following way to workaround VS 2013 bugs
template <size_t Rank, typename SourceType, typename TargetType, typename Ret = BoundsRangeConvertible2<typename SourceType::Base, typename TargetType::Base, Rank>>
auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret;
@@ -703,56 +660,55 @@
template <typename IndexType>
class bounds_iterator;
-template <typename SizeType, size_t... Ranges>
-class static_bounds {
+template <std::ptrdiff_t... Ranges>
+class static_bounds
+{
public:
- static_bounds(const details::BoundsRanges<SizeType, Ranges...> &) {
+ static_bounds(const details::BoundsRanges<Ranges...>&) {
}
};
-template <typename SizeType, size_t FirstRange, size_t... RestRanges>
-class static_bounds<SizeType, FirstRange, RestRanges...>
+template <std::ptrdiff_t FirstRange, std::ptrdiff_t... RestRanges>
+class static_bounds<FirstRange, RestRanges...>
{
- using MyRanges = details::BoundsRanges <SizeType, FirstRange, RestRanges... >;
- static_assert(std::is_integral<SizeType>::value
- && details::SizeTypeTraits<SizeType>::max_value <= SIZE_MAX, "SizeType must be an integral type and its numeric limits must be smaller than SIZE_MAX");
+ using MyRanges = details::BoundsRanges<FirstRange, RestRanges... >;
MyRanges m_ranges;
- constexpr static_bounds(const MyRanges & range) : m_ranges(range) { }
+ constexpr static_bounds(const MyRanges& range) : m_ranges(range)
+ {}
- template <typename SizeType2, size_t... Ranges2>
+ template <std::ptrdiff_t... OtherRanges>
friend class static_bounds;
+
public:
static const size_t rank = MyRanges::Depth;
static const size_t dynamic_rank = MyRanges::DynamicNum;
- static const SizeType static_size = static_cast<SizeType>(MyRanges::TotalSize);
+ static const std::ptrdiff_t static_size = MyRanges::TotalSize;
- using size_type = SizeType;
- using index_type = index<rank, size_type>;
+ using size_type = std::ptrdiff_t;
+ using index_type = index<rank>;
using iterator = bounds_iterator<index_type>;
using const_iterator = bounds_iterator<index_type>;
- using difference_type = ptrdiff_t;
- using sliced_type = static_bounds<SizeType, RestRanges...>;
+ using difference_type = std::ptrdiff_t;
+ using sliced_type = static_bounds<RestRanges...>;
using mapping_type = contiguous_mapping_tag;
public:
- constexpr static_bounds(const static_bounds &) = default;
+ constexpr static_bounds(const static_bounds&) = default;
- template <typename OtherSizeType, size_t... Ranges, typename Dummy = std::enable_if_t<
- details::BoundsRangeConvertible<details::BoundsRanges<OtherSizeType, Ranges...>, details::BoundsRanges <SizeType, FirstRange, RestRanges... >>::value>>
- constexpr static_bounds(const static_bounds<OtherSizeType, Ranges...> &other):
- m_ranges(other.m_ranges)
- {
- }
+ template <std::ptrdiff_t... Ranges, typename Dummy = std::enable_if_t<
+ details::BoundsRangeConvertible<details::BoundsRanges<Ranges...>, details::BoundsRanges <FirstRange, RestRanges... >>::value>>
+ constexpr static_bounds(const static_bounds<Ranges...>& other) : m_ranges(other.m_ranges)
+ {}
constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges(il.begin())
{
fail_fast_assert(MyRanges::DynamicNum == il.size(), "Size of the initializer list must match the rank of the array");
- fail_fast_assert(m_ranges.totalSize() <= details::SizeTypeTraits<size_type>::max_value, "Size of the range is larger than the max element of the size type");
+ fail_fast_assert(m_ranges.totalSize() <= PTRDIFF_MAX, "Size of the range is larger than the max element of the size type");
}
constexpr static_bounds() = default;
- constexpr static_bounds & operator = (const static_bounds & otherBounds)
+ constexpr static_bounds& operator=(const static_bounds& otherBounds)
{
new(&m_ranges) MyRanges (otherBounds.m_ranges);
return *this;
@@ -760,7 +716,7 @@
constexpr sliced_type slice() const noexcept
{
- return sliced_type{static_cast<const details::BoundsRanges<SizeType, RestRanges...> &>(m_ranges)};
+ return sliced_type{static_cast<const details::BoundsRanges<RestRanges...> &>(m_ranges)};
}
constexpr size_type stride() const noexcept
@@ -770,12 +726,12 @@
constexpr size_type size() const noexcept
{
- return static_cast<size_type>(m_ranges.totalSize());
+ return m_ranges.totalSize();
}
constexpr size_type total_size() const noexcept
{
- return static_cast<size_type>(m_ranges.totalSize());
+ return m_ranges.totalSize();
}
constexpr size_type linearize(const index_type & idx) const
@@ -807,14 +763,14 @@
return{ extents };
}
- template <typename OtherSizeTypes, size_t... Ranges>
- constexpr bool operator == (const static_bounds<OtherSizeTypes, Ranges...> & rhs) const noexcept
+ template <std::ptrdiff_t... Ranges>
+ constexpr bool operator == (const static_bounds<Ranges...>& rhs) const noexcept
{
return this->size() == rhs.size();
}
- template <typename OtherSizeTypes, size_t... Ranges>
- constexpr bool operator != (const static_bounds<OtherSizeTypes, Ranges...> & rhs) const noexcept
+ template <std::ptrdiff_t... Ranges>
+ constexpr bool operator != (const static_bounds<Ranges...>& rhs) const noexcept
{
return !(*this == rhs);
}
@@ -830,10 +786,13 @@
}
};
-template <size_t Rank, typename SizeType = size_t>
-class strided_bounds
+template <size_t Rank>
+class strided_bounds : private details::coordinate_facade<strided_bounds<Rank>, Rank>
{
- template <size_t OtherRank, typename OtherSizeType>
+ using Base = details::coordinate_facade<strided_bounds<Rank>, Rank>;
+ friend Base;
+
+ template <size_t OtherRank>
friend class strided_bounds;
public:
@@ -846,23 +805,33 @@
using index_type = index<rank, size_type>;
using iterator = bounds_iterator<index_type>;
using const_iterator = bounds_iterator<index_type>;
- static const int dynamic_rank = rank;
- static const size_t static_size = dynamic_range;
+ static const size_t dynamic_rank = rank;
+ static const std::ptrdiff_t static_size = dynamic_range;
using sliced_type = std::conditional_t<rank != 0, strided_bounds<rank - 1>, void>;
using mapping_type = generalized_mapping_tag;
+
constexpr strided_bounds(const strided_bounds &) noexcept = default;
- template <typename OtherSizeType>
- constexpr strided_bounds(const strided_bounds<rank, OtherSizeType> &other) noexcept
- : m_extents(other.extents), m_strides(other.strides)
- {}
+ constexpr strided_bounds(const index_type& extents, const index_type& strides)
+ : m_strides(strides)
+ {
+ for (size_t i = 0; i < rank; i++)
+ Base::elems[i] = extents[i];
+ }
+
+ constexpr strided_bounds(const value_type(&values)[rank], index_type strides)
+ : Base(values), m_strides(std::move(strides))
+ {}
+
constexpr strided_bounds(const index_type &extents, const index_type &strides) noexcept
: m_extents(extents), m_strides(strides)
{}
+
constexpr index_type strides() const noexcept
{
return m_strides;
}
+
constexpr size_type total_size() const noexcept
{
size_type ret = 0;
@@ -872,7 +841,8 @@
}
return ret + 1;
}
- constexpr size_type size() const noexcept
+
+ constexpr size_type size() const noexcept
{
size_type ret = 1;
for (size_t i = 0; i < rank; ++i)
@@ -881,7 +851,8 @@
}
return ret;
}
- constexpr bool contains(const index_type& idx) const noexcept
+
+ constexpr bool contains(const index_type& idx) const noexcept
{
for (size_t i = 0; i < rank; ++i)
{
@@ -890,7 +861,8 @@
}
return true;
}
- constexpr size_type linearize(const index_type & idx) const noexcept
+
+ constexpr size_type linearize(const index_type& idx) const noexcept
{
size_type ret = 0;
for (size_t i = 0; i < rank; i++)
@@ -900,33 +872,40 @@
}
return ret;
}
- constexpr size_type stride() const noexcept
+
+ constexpr size_type stride() const noexcept
{
return m_strides[0];
}
- template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
+
+ template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
constexpr sliced_type slice() const
{
return{ details::shift_left(m_extents), details::shift_left(m_strides) };
}
- template <size_t Dim = 0>
+
+ template <size_t Dim = 0>
constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)");
return m_extents[Dim];
}
- constexpr index_type index_bounds() const noexcept
+
+ constexpr index_type index_bounds() const noexcept
{
return m_extents;
}
- const_iterator begin() const noexcept
+
+ const_iterator begin() const noexcept
{
return const_iterator{ *this };
}
- const_iterator end() const noexcept
+
+ const_iterator end() const noexcept
{
return const_iterator{ *this, index_bounds() };
}
+
private:
index_type m_extents;
index_type m_strides;
@@ -934,10 +913,10 @@
template <typename T>
struct is_bounds : std::integral_constant<bool, false> {};
-template <typename SizeType, size_t... Ranges>
-struct is_bounds<static_bounds<SizeType, Ranges...>> : std::integral_constant<bool, true> {};
-template <size_t Rank, typename SizeType>
-struct is_bounds<strided_bounds<Rank, SizeType>> : std::integral_constant<bool, true> {};
+template <std::ptrdiff_t... Ranges>
+struct is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true> {};
+template <size_t Rank>
+struct is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true> {};
template <typename IndexType>
class bounds_iterator
@@ -1133,26 +1112,26 @@
value_type curr;
};
-template <typename SizeType>
-class bounds_iterator<index<1, SizeType>>
+template <>
+class bounds_iterator<index<1>>
: public std::iterator<std::random_access_iterator_tag,
- index<1, SizeType>,
+ index<1>,
ptrdiff_t,
- const details::arrow_proxy<index<1, SizeType>>,
- const index<1, SizeType>>
+ const details::arrow_proxy<index<1>>,
+ const index<1>>
{
- using Base = std::iterator<std::random_access_iterator_tag, index<1, SizeType>, ptrdiff_t, const details::arrow_proxy<index<1, SizeType>>, const index<1, SizeType>>;
+ using Base = std::iterator<std::random_access_iterator_tag, index<1>, std::ptrdiff_t, const details::arrow_proxy<index<1>>, const index<1>>;
public:
- using typename Base::reference;
- using typename Base::pointer;
- using typename Base::difference_type;
- using typename Base::value_type;
+ using Base::reference;
+ using Base::pointer;
+ using Base::difference_type;
+ using Base::value_type;
using index_type = value_type;
- using index_size_type = typename index_type::value_type;
+ using index_size_type = index_type::size_type;
template <typename Bounds>
- explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) noexcept
+ explicit bounds_iterator(const Bounds&, value_type curr = value_type{}) noexcept
: curr( std::move(curr) )
{}
reference operator*() const noexcept
@@ -1250,9 +1229,9 @@
return rhs + n;
}
-/*
-** begin definitions of basic_array_view
-*/
+//
+// begin definitions of basic_array_view
+//
namespace details
{
template <typename Bounds>
@@ -1461,22 +1440,23 @@
friend class basic_array_view;
};
-template <size_t DimSize = dynamic_range>
+template <std::ptrdiff_t DimSize = dynamic_range>
struct dim
{
- static const size_t value = DimSize;
+ static const std::ptrdiff_t value = DimSize;
};
template <>
struct dim<dynamic_range>
{
- static const size_t value = dynamic_range;
- const size_t dvalue;
- dim(size_t size) : dvalue(size) {}
+ static const std::ptrdiff_t value = dynamic_range;
+ const std::ptrdiff_t dvalue;
+ dim(std::ptrdiff_t size) : dvalue(size) {}
};
-template <typename ValueTypeOpt, size_t FirstDimension = dynamic_range, size_t... RestDimensions>
+template <typename ValueType, std::ptrdiff_t FirstDimension = dynamic_range, std::ptrdiff_t... RestDimensions>
class array_view;
-template <typename ValueTypeOpt, size_t Rank>
+
+template <typename ValueType, size_t Rank>
class strided_array_view;
namespace details
@@ -1495,31 +1475,31 @@
using size_type = typename Traits::array_view_traits::size_type;
};
- template <typename T, typename SizeType, size_t... Ranks>
+ template <typename T, size_t... Ranks>
struct ArrayViewArrayTraits {
using type = array_view<T, Ranks...>;
using value_type = T;
- using bounds_type = static_bounds<SizeType, Ranks...>;
+ using bounds_type = static_bounds<Ranks...>;
using pointer = T*;
using reference = T&;
};
- template <typename T, typename SizeType, size_t N, size_t... Ranks>
- struct ArrayViewArrayTraits<T[N], SizeType, Ranks...> : ArrayViewArrayTraits<T, SizeType, Ranks..., N> {};
+ template <typename T, size_t N, size_t... Ranks>
+ struct ArrayViewArrayTraits<T[N], Ranks...> : ArrayViewArrayTraits<T, Ranks..., N> {};
template <typename BoundsType>
- BoundsType newBoundsHelperImpl(size_t totalSize, std::true_type) // dynamic size
+ BoundsType newBoundsHelperImpl(std::ptrdiff_t , std::true_type) // dynamic size
{
- fail_fast_assert(totalSize <= details::SizeTypeTraits<typename BoundsType::size_type>::max_value);
- return BoundsType{static_cast<typename BoundsType::size_type>(totalSize)};
+ fail_fast_assert(totalSize <= PTRDIFF_MAX);
+ return BoundsType{totalSize};
}
template <typename BoundsType>
- BoundsType newBoundsHelperImpl(size_t totalSize, std::false_type) // static size
+ BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size
{
fail_fast_assert(BoundsType::static_size == totalSize);
return {};
}
template <typename BoundsType>
- BoundsType newBoundsHelper(size_t totalSize)
+ BoundsType newBoundsHelper(std::ptrdiff_t totalSize)
{
static_assert(BoundsType::dynamic_rank <= 1, "dynamic rank must less or equal to 1");
return newBoundsHelperImpl<BoundsType>(totalSize, std::integral_constant<bool, BoundsType::dynamic_rank == 1>());
@@ -1543,46 +1523,38 @@
return static_as_array_view_helper<T>(args..., val.dvalue);
}
- template <typename SizeType, typename ...Dimensions>
+ template <typename ...Dimensions>
struct static_as_array_view_static_bounds_helper
{
- using type = static_bounds<SizeType, (Dimensions::value)...>;
+ using type = static_bounds<(Dimensions::value)...>;
};
template <typename T>
struct is_array_view_oracle : std::false_type
{};
- template <typename ValueType, size_t FirstDimension, size_t... RestDimensions>
+
+ template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
struct is_array_view_oracle<array_view<ValueType, FirstDimension, RestDimensions...>> : std::true_type
{};
- template <typename ValueType, size_t Rank>
+
+ template <typename ValueType, size_t Rank>
struct is_array_view_oracle<strided_array_view<ValueType, Rank>> : std::true_type
{};
- template <typename T>
+
+ template <typename T>
struct is_array_view : is_array_view_oracle<std::remove_cv_t<T>>
{};
}
-template <typename ValueType, typename SizeType>
-struct array_view_options
+template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
+class array_view : public basic_array_view <ValueType, static_bounds <FirstDimension, RestDimensions...>>
{
- struct array_view_traits
- {
- using value_type = ValueType;
- using size_type = SizeType;
- };
-};
-
-template <typename ValueTypeOpt, size_t FirstDimension, size_t... RestDimensions>
-class array_view : public basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type,
- static_bounds<typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type, FirstDimension, RestDimensions...>>
-{
- template <typename ValueTypeOpt2, size_t FirstDimension2, size_t... RestDimensions2>
+ template <typename ValueType2, std::ptrdiff_t FirstDimension2, std::ptrdiff_t... RestDimensions2>
friend class array_view;
- using Base = basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type,
- static_bounds<typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type, FirstDimension, RestDimensions...>>;
+
+ using Base = basic_array_view<ValueType, static_bounds<FirstDimension, RestDimensions...>>;
public:
using typename Base::bounds_type;
@@ -1597,13 +1569,14 @@
public:
// basic
- constexpr array_view(pointer ptr, bounds_type bounds) : Base(ptr, std::move(bounds))
- {
- }
+ constexpr array_view(pointer ptr, size_type size) : Base(ptr, bounds_type{ size })
+ {}
+
+ constexpr array_view(pointer ptr, bounds_type bounds) : Base(ptr, std::move(bounds))
+ {}
constexpr array_view(std::nullptr_t) : Base(nullptr, bounds_type{})
- {
- }
+ {}
constexpr array_view(std::nullptr_t, size_type size) : Base(nullptr, bounds_type{})
{
@@ -1613,108 +1586,102 @@
// default
template <size_t DynamicRank = bounds_type::dynamic_rank, typename Dummy = std::enable_if_t<DynamicRank != 0>>
constexpr array_view() : Base(nullptr, bounds_type())
- {
- }
+ {}
// from n-dimensions dynamic array (e.g. new int[m][4]) (precedence will be lower than the 1-dimension pointer)
- template <typename T, typename Helper = details::ArrayViewArrayTraits<T, size_type, dynamic_range>,
- typename Dummy = std::enable_if_t<std::is_convertible<typename Helper::value_type (*)[], typename Base::value_type (*)[]>::value
- && std::is_convertible<typename Helper::bounds_type, typename Base::bounds_type>::value>>
- constexpr array_view(T * const & data, size_type size) : Base(data, typename Helper::bounds_type{size})
- {
- }
+ template <typename T, typename Helper = details::ArrayViewArrayTraits<T, dynamic_range>
+ typename Dummy = std::enable_if_t<std::is_convertible<Helper::value_type (*)[], typename Base::value_type (*)[]>::value>>
+ constexpr array_view(T* const& data, size_type size) : Base(data, typename Helper::bounds_type{size})
+ {}
// from n-dimensions static array
- template <typename T, size_t N, typename Helper = details::ArrayViewArrayTraits<T, size_type, N>,
- typename Dummy = std::enable_if_t<std::is_convertible<typename Helper::value_type(*)[], typename Base::value_type(*)[]>::value
- && std::is_convertible<typename Helper::bounds_type, typename Base::bounds_type>::value>>
+ template <typename T, size_t N, typename Helper = details::ArrayViewArrayTraits<T, dynamic_range>
+ typename Dummy = std::enable_if_t<std::is_convertible<typename Helper::value_type(*)[], typename Base::value_type(*)[]>::value>
+ >
constexpr array_view (T (&arr)[N]) : Base(arr, typename Helper::bounds_type())
- {
- }
+ {}
// from n-dimensions static array with size
- template <typename T, size_t N, typename Helper = details::ArrayViewArrayTraits<T, size_type, dynamic_range>,
- typename Dummy = std::enable_if_t<std::is_convertible<typename Helper::value_type(*)[], typename Base::value_type(*)[]>::value
- && std::is_convertible<typename Helper::bounds_type, typename Base::bounds_type>::value >>
+ template <typename T, size_t N,
+ typename Dummy = std::enable_if_t<std::is_convertible<T(*)[], typename Base::value_type(*)[]>::value>
+ >
constexpr array_view(T(&arr)[N], size_type size) : Base(arr, typename Helper::bounds_type{ size })
{
fail_fast_assert(size <= N);
}
// from std array
- template <size_t N, typename Dummy = std::enable_if_t<std::is_convertible<static_bounds<size_type, N>, typename Base::bounds_type>::value>>
- constexpr array_view (std::array<std::remove_const_t<value_type>, N> & arr) : Base(arr.data(), static_bounds<size_type, N>())
- {
- }
+ template <size_t N,
+ typename Dummy = std::enable_if_t<std::is_convertible<static_bounds<N>, typename Base::bounds_type>::value>
+ >
+ constexpr array_view (std::array<std::remove_const_t<value_type>, N> & arr) : Base(arr.data(), static_bounds<N>())
+ {}
- template <size_t N, typename Dummy = std::enable_if_t<std::is_convertible<static_bounds<size_type, N>, typename Base::bounds_type>::value && std::is_const<value_type>::value>>
- constexpr array_view (const std::array<std::remove_const_t<value_type>, N> & arr) : Base(arr.data(), static_bounds<size_type, N>())
- {
- }
-
-
+ template <size_t N,
+ typename Dummy = std::enable_if_t<std::is_convertible<static_bounds<N>, typename Base::bounds_type>::value
+ && std::is_const<value_type>::value>
+ >
+ constexpr array_view (const std::array<std::remove_const_t<value_type>, N> & arr) : Base(arr.data(), static_bounds<N>())
+ {}
+
// from begin, end pointers. We don't provide iterator pair since no way to guarantee the contiguity
template <typename Ptr,
typename Dummy = std::enable_if_t<std::is_convertible<Ptr, pointer>::value
- && details::LessThan<Base::bounds_type::dynamic_rank, 2>::value>> // remove literal 0 case
+ && details::LessThan<Base::bounds_type::dynamic_rank, 2>::value>
+ > // remove literal 0 case
constexpr array_view (pointer begin, Ptr end) : Base(begin, details::newBoundsHelper<typename Base::bounds_type>(static_cast<pointer>(end) - begin))
- {
- }
+ {}
// from containers. It must has .size() and .data() two function signatures
- template <typename Cont, typename DataType = typename Cont::value_type, typename SizeType = typename Cont::size_type,
+ template <typename Cont, typename DataType = typename Cont::value_type,
typename Dummy = std::enable_if_t<!details::is_array_view<Cont>::value
&& std::is_convertible<DataType (*)[], typename Base::value_type (*)[]>::value
- && std::is_convertible<static_bounds<SizeType, dynamic_range>, typename Base::bounds_type>::value
&& std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), *std::declval<Cont>().data())>, DataType>::value>
>
constexpr array_view (Cont& cont) : Base(static_cast<pointer>(cont.data()), details::newBoundsHelper<typename Base::bounds_type>(cont.size()))
- {
+ {}
- }
-
- constexpr array_view(const array_view &) = default;
+ constexpr array_view(const array_view &) = default;
// convertible
- template <typename OtherValueTypeOpt, size_t... OtherDimensions,
- typename BaseType = basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, static_bounds<typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type, FirstDimension, RestDimensions...>>,
- typename OtherBaseType = basic_array_view<typename details::ArrayViewTypeTraits<OtherValueTypeOpt>::value_type, static_bounds<typename details::ArrayViewTypeTraits<OtherValueTypeOpt>::size_type, OtherDimensions...>>,
+ template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
+ typename BaseType = basic_array_view<ValueType, static_bounds<FirstDimension, RestDimensions...>>,
+ typename OtherBaseType = basic_array_view<OtherValueType, static_bounds<OtherDimensions...>>,
typename Dummy = std::enable_if_t<std::is_convertible<OtherBaseType, BaseType>::value>
>
- constexpr array_view(const array_view<OtherValueTypeOpt, OtherDimensions...> &av) : Base(static_cast<const typename array_view<OtherValueTypeOpt, OtherDimensions...>::Base &>(av)) {} // static_cast is required
+ constexpr array_view(const array_view<OtherValueType, OtherDimensions...> &av)
+ : Base(static_cast<const typename array_view<OtherValueType, OtherDimensions...>::Base&>(av))
+ {}
// reshape
template <typename... Dimensions2>
- constexpr array_view<ValueTypeOpt, Dimensions2::value...> as_array_view(Dimensions2... dims)
+ constexpr array_view<ValueType, Dimensions2::value...> as_array_view(Dimensions2... dims)
{
static_assert(sizeof...(Dimensions2) > 0, "the target array_view must have at least one dimension.");
- using BoundsType = typename array_view<ValueTypeOpt, (Dimensions2::value)...>::bounds_type;
+ using BoundsType = typename array_view<ValueType, (Dimensions2::value)...>::bounds_type;
auto tobounds = details::static_as_array_view_helper<BoundsType>(dims..., details::Sep{});
details::verifyBoundsReshape(this->bounds(), tobounds);
return {this->data(), tobounds};
}
// to bytes array
- template <bool Enabled = std::is_standard_layout<std::decay_t<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type>>::value>
- constexpr auto as_bytes() const noexcept ->
- array_view<array_view_options<const byte, size_type>, static_cast<size_t>(details::StaticSizeHelper<size_type, Base::bounds_type::static_size, sizeof(value_type)>::value)>
+ template <bool Enabled = std::is_standard_layout<std::decay_t<ValueType>>::value>
+ constexpr auto as_bytes() const noexcept -> array_view<const byte>
{
static_assert(Enabled, "The value_type of array_view must be standarded layout");
return { reinterpret_cast<const byte*>(this->data()), this->bytes() };
}
- template <bool Enabled = std::is_standard_layout<std::decay_t<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type>>::value>
- constexpr auto as_writeable_bytes() const noexcept ->
- array_view<array_view_options<byte, size_type>, static_cast<size_t>(details::StaticSizeHelper<size_type, Base::bounds_type::static_size, sizeof(value_type)>::value)>
+ template <bool Enabled = std::is_standard_layout<std::decay_t<ValueType>>::value>
+ constexpr auto as_writeable_bytes() const noexcept -> array_view<byte>
{
static_assert(Enabled, "The value_type of array_view must be standarded layout");
return { reinterpret_cast<byte*>(this->data()), this->bytes() };
}
-
- // from bytes array
+ // from bytes array
template<typename U, bool IsByte = std::is_same<value_type, const byte>::value, typename Dummy = std::enable_if_t<IsByte && sizeof...(RestDimensions) == 0>>
- constexpr auto as_array_view() const noexcept -> array_view<const U, (Base::bounds_type::dynamic_rank == 0 ? Base::bounds_type::static_size / sizeof(U) : static_cast<size_type>(dynamic_range))>
+ constexpr auto as_array_view() const noexcept -> array_view<const U, (Base::bounds_type::dynamic_rank == 0 ? Base::bounds_type::static_size / sizeof(U) : dynamic_range)>
{
static_assert(std::is_standard_layout<U>::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0),
"Target type must be standard layout and its size must match the byte array size");
@@ -1723,7 +1690,7 @@
}
template<typename U, bool IsByte = std::is_same<value_type, byte>::value, typename Dummy = std::enable_if_t<IsByte && sizeof...(RestDimensions) == 0>>
- constexpr auto as_array_view() const noexcept -> array_view<U, (Base::bounds_type::dynamic_rank == 0 ? Base::bounds_type::static_size / sizeof(U) : static_cast<size_type>(dynamic_range))>
+ constexpr auto as_array_view() const noexcept -> array_view<U, (Base::bounds_type::dynamic_rank == 0 ? Base::bounds_type::static_size / sizeof(U) : dynamic_range)>
{
static_assert(std::is_standard_layout<U>::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0),
"Target type must be standard layout and its size must match the byte array size");
@@ -1732,43 +1699,43 @@
}
// section on linear space
- template<size_t Count>
- constexpr array_view<ValueTypeOpt, Count> first() const noexcept
+ template<std::ptrdiff_t Count>
+ constexpr array_view<ValueType, Count> first() const noexcept
{
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); // ensures we only check condition when needed
return { this->data(), Count };
}
- constexpr array_view<ValueTypeOpt, dynamic_range> first(size_type count) const noexcept
+ constexpr array_view<ValueType, dynamic_range> first(size_type count) const noexcept
{
fail_fast_assert(count <= this->size());
return { this->data(), count };
}
- template<size_t Count>
- constexpr array_view<ValueTypeOpt, Count> last() const noexcept
+ template<std::ptrdiff_t Count>
+ constexpr array_view<ValueType, Count> last() const noexcept
{
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size());
return { this->data() + this->size() - Count, Count };
}
- constexpr array_view<ValueTypeOpt, dynamic_range> last(size_type count) const noexcept
+ constexpr array_view<ValueType, dynamic_range> last(size_type count) const noexcept
{
fail_fast_assert(count <= this->size());
return { this->data() + this->size() - count, count };
}
- template<size_t Offset, size_t Count>
- constexpr array_view<ValueTypeOpt, Count> sub() const noexcept
+ template<std::ptrdiff_t Offset, std::ptrdiff_t Count>
+ constexpr array_view<ValueType, Count> sub() const noexcept
{
static_assert(bounds_type::static_size == dynamic_range || ((Offset == 0 || Offset <= bounds_type::static_size) && Offset + Count <= bounds_type::static_size), "Index is out of bound");
fail_fast_assert(bounds_type::static_size != dynamic_range || ((Offset == 0 || Offset <= this->size()) && Offset + Count <= this->size()));
return { this->data() + Offset, Count };
}
- constexpr array_view<ValueTypeOpt, dynamic_range> sub(size_type offset, size_type count = dynamic_range) const noexcept
+ constexpr array_view<ValueType, dynamic_range> sub(size_type offset, size_type count = dynamic_range) const noexcept
{
fail_fast_assert((offset == 0 || offset <= this->size()) && (count == dynamic_range || (offset + count) <= this->size()));
return { this->data() + offset, count == dynamic_range ? this->length() - offset : count };
@@ -1779,24 +1746,27 @@
{
return this->size();
}
+
constexpr size_type used_length() const noexcept
{
return length();
}
+
constexpr size_type bytes() const noexcept
{
return sizeof(value_type) * this->size();
}
+
constexpr size_type used_bytes() const noexcept
{
return bytes();
}
// section
- constexpr strided_array_view<ValueTypeOpt, rank> section(index_type origin, index_type extents) const
+ constexpr strided_array_view<ValueType, rank> section(index_type origin, index_type extents) const
{
size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
- return{ &this->operator[](origin), size, strided_bounds<rank, size_type> {extents, details::make_stride(Base::bounds())} };
+ return{ &this->operator[](origin), size, strided_bounds<rank> {extents, details::make_stride(Base::bounds())} };
}
constexpr reference operator[](const index_type& idx) const
@@ -1805,7 +1775,7 @@
}
template <bool Enabled = (rank > 1), typename Dummy = std::enable_if_t<Enabled>>
- constexpr array_view<ValueTypeOpt, RestDimensions...> operator[](size_type idx) const
+ constexpr array_view<ValueType, RestDimensions...> operator[](size_type idx) const
{
auto ret = Base::operator[](idx);
return{ ret.data(), ret.bounds() };
@@ -1819,20 +1789,20 @@
using Base::operator>=;
};
-template <typename T, size_t... Dimensions>
-constexpr auto as_array_view(T * const & ptr, dim<Dimensions>... args) -> array_view<std::remove_all_extents_t<T>, Dimensions...>
+template <typename T, std::ptrdiff_t... Dimensions>
+constexpr auto as_array_view(T* const& ptr, dim<Dimensions>... args) -> array_view<std::remove_all_extents_t<T>, Dimensions...>
{
- return {reinterpret_cast<std::remove_all_extents_t<T>*>(ptr), details::static_as_array_view_helper<static_bounds<size_t, Dimensions...>>(args..., details::Sep{})};
+ return {reinterpret_cast<std::remove_all_extents_t<T>*>(ptr), details::static_as_array_view_helper<static_bounds<Dimensions...>>(args..., details::Sep{})};
}
template <typename T>
-constexpr auto as_array_view (T * arr, size_t len) -> typename details::ArrayViewArrayTraits<T, size_t, dynamic_range>::type
+constexpr auto as_array_view (T* arr, std::ptrdiff_t len) -> typename details::ArrayViewArrayTraits<T, dynamic_range>::type
{
- return {arr, len};
+ return {reinterpret_cast<std::remove_all_extents_t<T>*>(arr), len};
}
template <typename T, size_t N>
-constexpr auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits<T, size_t, N>::type
+constexpr auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits<T, N>::type
{
return {arr};
}
@@ -1869,13 +1839,14 @@
constexpr auto as_array_view(Cont &&arr) -> std::enable_if_t<!details::is_array_view<std::decay_t<Cont>>::value,
array_view<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete;
-template <typename ValueTypeOpt, size_t Rank>
-class strided_array_view : public basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type>>
+template <typename ValueType, size_t Rank>
+class strided_array_view : public basic_array_view<ValueType, strided_bounds<Rank>>
{
- using Base = basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type>>;
+ using Base = basic_array_view<ValueType, strided_bounds<Rank>>;
- template<typename OtherValueOpt, size_t OtherRank>
+ template<typename OtherValue, size_t OtherRank>
friend class strided_array_view;
+
public:
using Base::rank;
using typename Base::bounds_type;
@@ -1901,21 +1872,20 @@
}
// from array view
- template <size_t... Dimensions, typename Dummy = std::enable_if<sizeof...(Dimensions) == Rank>>
- strided_array_view(array_view<ValueTypeOpt, Dimensions...> av, bounds_type bounds) : Base(av.data(), std::move(bounds))
+ template <std::ptrdiff_t... Dimensions, typename Dummy = std::enable_if<sizeof...(Dimensions) == Rank>>
+ strided_array_view(array_view<ValueType, Dimensions...> av, bounds_type bounds) : Base(av.data(), std::move(bounds))
{
fail_fast_assert(this->bounds().total_size() <= av.bounds().total_size(), "Bounds cross data boundaries");
}
// convertible
- template <typename OtherValueTypeOpt,
- typename BaseType = basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type>>,
- typename OtherBaseType = basic_array_view<typename details::ArrayViewTypeTraits<OtherValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<OtherValueTypeOpt>::size_type>>,
+ template <typename OtherValueType,
+ typename BaseType = basic_array_view<ValueType, strided_bounds<Rank>>,
+ typename OtherBaseType = basic_array_view<OtherValueType, strided_bounds<Rank>>,
typename Dummy = std::enable_if_t<std::is_convertible<OtherBaseType, BaseType>::value>
>
- constexpr strided_array_view(const strided_array_view<OtherValueTypeOpt, Rank> &av): Base(static_cast<const typename strided_array_view<OtherValueTypeOpt, Rank>::Base &>(av)) // static_cast is required
- {
- }
+ constexpr strided_array_view(const strided_array_view<OtherValueType, Rank> &av) : Base(static_cast<const typename strided_array_view<OtherValueType, Rank>::Base &>(av)) // static_cast is required
+ {}
// convert from bytes
template <typename OtherValueType>
@@ -1989,17 +1959,21 @@
using typename Base::reference;
using typename Base::pointer;
using typename Base::difference_type;
+
private:
template <typename ValueType, typename Bounds>
friend class basic_array_view;
- pointer m_pdata;
+
+ pointer m_pdata;
const ArrayView * m_validator;
void validateThis() const
{
fail_fast_assert(m_pdata >= m_validator->m_pdata && m_pdata < m_validator->m_pdata + m_validator->size(), "iterator is out of range of the array");
}
- contiguous_array_view_iterator (const ArrayView *container, bool isbegin = false) :
+
+ contiguous_array_view_iterator (const ArrayView *container, bool isbegin = false) :
m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) { }
+
public:
reference operator*() const noexcept
{
@@ -2112,12 +2086,14 @@
private:
template <typename ValueType, typename Bounds>
friend class basic_array_view;
- const ArrayView * m_container;
+
+ const ArrayView * m_container;
typename ArrayView::bounds_type::iterator m_itr;
- general_array_view_iterator(const ArrayView *container, bool isbegin = false) :
- m_container(container), m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
- {
- }
+
+ general_array_view_iterator(const ArrayView *container, bool isbegin = false) :
+ m_container(container), m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
+ {}
+
public:
reference operator*() const noexcept
{
diff --git a/include/string_view.h b/include/string_view.h
index 4076d52..04909f8 100644
--- a/include/string_view.h
+++ b/include/string_view.h
@@ -34,16 +34,16 @@
// type system for these types that will not either incur significant runtime costs or
// (sometimes needlessly) break existing programs when introduced.
//
-template<size_t Max = dynamic_range>
+template<std::ptrdiff_t Max = dynamic_range>
using czstring = const char*;
-template<size_t Max = dynamic_range>
+template<std::ptrdiff_t Max = dynamic_range>
using cwzstring = const wchar_t*;
-template<size_t Max = dynamic_range>
+template<std::ptrdiff_t Max = dynamic_range>
using zstring = char*;
-template<size_t Max = dynamic_range>
+template<std::ptrdiff_t Max = dynamic_range>
using wzstring = wchar_t*;
//
@@ -54,19 +54,19 @@
//
// TODO (neilmac) once array_view regains configurable size_type, update these typedef's
//
-template <class CharT, size_t Extent = dynamic_range>
+template <class CharT, std::ptrdiff_t Extent = dynamic_range>
using basic_string_view = array_view<CharT, Extent>;
-template<size_t Extent = dynamic_range>
+template<std::ptrdiff_t Extent = dynamic_range>
using string_view = basic_string_view<char, Extent>;
-template<size_t Extent = dynamic_range>
+template<std::ptrdiff_t Extent = dynamic_range>
using cstring_view = basic_string_view<const char, Extent>;
-template<size_t Extent = dynamic_range>
+template<std::ptrdiff_t Extent = dynamic_range>
using wstring_view = basic_string_view<wchar_t, Extent>;
-template<size_t Extent = dynamic_range>
+template<std::ptrdiff_t Extent = dynamic_range>
using cwstring_view = basic_string_view<const wchar_t, Extent>;
@@ -94,38 +94,39 @@
// the limit of size_type.
//
template<class T>
-inline basic_string_view<T, dynamic_range> ensure_z(T* const & sz, size_t max = std::numeric_limits<size_t>::max())
+inline basic_string_view<T, dynamic_range> ensure_z(T* const & sz, std::ptrdiff_t max = PTRDIFF_MAX)
{
return ensure_sentinel<0>(sz, max);
}
// TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation
-inline basic_string_view<char, dynamic_range> ensure_z(char* const & sz, size_t max)
+inline basic_string_view<char, dynamic_range> ensure_z(char* const& sz, std::ptrdiff_t max)
{
auto len = strnlen(sz, max);
- fail_fast_assert(sz[len] == 0); return{ sz, len };
+ fail_fast_assert(sz[len] == 0);
+ return{ sz, static_cast<std::ptrdiff_t>(len) };
}
-inline basic_string_view<const char, dynamic_range> ensure_z(const char* const& sz, size_t max)
+inline basic_string_view<const char, dynamic_range> ensure_z(const char* const& sz, std::ptrdiff_t max)
{
auto len = strnlen(sz, max);
- fail_fast_assert(sz[len] == 0); return{ sz, len };
+ fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
}
-inline basic_string_view<wchar_t, dynamic_range> ensure_z(wchar_t* const & sz, size_t max)
+inline basic_string_view<wchar_t, dynamic_range> ensure_z(wchar_t* const& sz, std::ptrdiff_t max)
{
auto len = wcsnlen(sz, max);
- fail_fast_assert(sz[len] == 0); return{ sz, len };
+ fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
}
-inline basic_string_view<const wchar_t, dynamic_range> ensure_z(const wchar_t* const & sz, size_t max)
+inline basic_string_view<const wchar_t, dynamic_range> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max)
{
auto len = wcsnlen(sz, max);
- fail_fast_assert(sz[len] == 0); return{ sz, len };
+ fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
}
template<class T, size_t N>
-basic_string_view<T, dynamic_range> ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], N); }
+basic_string_view<T, dynamic_range> ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], static_cast<std::ptrdiff_t>(N)); }
template<class Cont>
basic_string_view<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_range> ensure_z(Cont& cont)
diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp
index f84e908..19889c3 100644
--- a/tests/array_view_tests.cpp
+++ b/tests/array_view_tests.cpp
@@ -51,7 +51,7 @@
delete[] ptr.data();
- static_bounds<size_t, 4, dynamic_range, 2> bounds{ 3 };
+ static_bounds<4, dynamic_range, 2> bounds{ 3 };
#ifdef CONFIRM_COMPILATION_ERRORS
array_view<int, 4, dynamic_range, 2> av(nullptr, bounds);
@@ -152,9 +152,9 @@
TEST(md_access)
{
- unsigned int width = 5, height = 20;
+ auto width = 5, height = 20;
- unsigned int imgSize = width * height;
+ auto imgSize = width * height;
auto image_ptr = new int[imgSize][3];
// size check will be done
@@ -163,9 +163,9 @@
iota(image_view.begin(), image_view.end(), 1);
int expected = 0;
- for (unsigned int i = 0; i < height; i++)
+ for (auto i = 0; i < height; i++)
{
- for (unsigned int j = 0; j < width; j++)
+ for (auto j = 0; j < width; j++)
{
CHECK(expected + 1 == image_view[i][j][0]);
CHECK(expected + 2 == image_view[i][j][1]);
@@ -245,7 +245,7 @@
auto av8 = av7.as_array_view<int>();
CHECK(av8.size() == av6.size());
- for (size_t i = 0; i < av8.size(); i++)
+ for (auto i = 0; i < av8.size(); i++)
{
CHECK(av8[i] == 1);
}
diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp
index c3f549f..aacf3d8 100644
--- a/tests/bounds_tests.cpp
+++ b/tests/bounds_tests.cpp
@@ -23,16 +23,16 @@
namespace
{
- void use(unsigned int&) {}
+ void use(std::ptrdiff_t&) {}
}
SUITE(bounds_test)
{
TEST(basic_bounds)
{
- for (auto point : static_bounds <unsigned int, dynamic_range, 3, 4 > { 2 })
+ for (auto point : static_bounds<dynamic_range, 3, 4 > { 2 })
{
- for (unsigned int j = 0; j < decltype(point)::rank; j++)
+ for (decltype(point)::size_type j = 0; j < decltype(point)::rank; j++)
{
use(j);
use(point[j]);
@@ -42,24 +42,24 @@
TEST(bounds_basic)
{
- static_bounds<size_t, 3, 4, 5> b;
+ static_bounds<3, 4, 5> b;
auto a = b.slice();
- static_bounds<size_t, 4, dynamic_range, 2> x{ 4 };
+ static_bounds<4, dynamic_range, 2> x{ 4 };
x.slice().slice();
}
TEST (arrayview_iterator)
{
- static_bounds<size_t, 4, dynamic_range, 2> bounds{ 3 };
+ static_bounds<4, dynamic_range, 2> bounds{ 3 };
auto itr = bounds.begin();
#ifdef CONFIRM_COMPILATION_ERRORS
- array_view< int, 4, dynamic_range, 2> av(nullptr, bounds);
+ array_view<int, 4, dynamic_range, 2> av(nullptr, bounds);
auto itr2 = av.cbegin();
- for (auto & v : av) {
+ for (auto& v : av) {
v = 4;
}
fill(av.begin(), av.end(), 0);
@@ -68,24 +68,24 @@
TEST (bounds_convertible)
{
- static_bounds<size_t, 7, 4, 2> b1;
- static_bounds<size_t, 7, dynamic_range, 2> b2 = b1;
+ static_bounds<7, 4, 2> b1;
+ static_bounds<7, dynamic_range, 2> b2 = b1;
#ifdef CONFIRM_COMPILATION_ERRORS
- static_bounds<size_t, 7, dynamic_range, 1> b4 = b2;
+ static_bounds<7, dynamic_range, 1> b4 = b2;
#endif
- static_bounds<size_t, dynamic_range, dynamic_range, dynamic_range> b3 = b1;
- static_bounds<int, 7, 4, 2> b4 = b3;
+ static_bounds<dynamic_range, dynamic_range, dynamic_range> b3 = b1;
+ static_bounds<7, 4, 2> b4 = b3;
- static_bounds<size_t, dynamic_range> b11;
+ static_bounds<dynamic_range> b11;
- static_bounds<size_t, dynamic_range> b5;
- static_bounds<size_t, 34> b6;
+ static_bounds<dynamic_range> b5;
+ static_bounds<34> b6;
- b5 = static_bounds<size_t, 20>();
+ b5 = static_bounds<20>();
CHECK_THROW(b6 = b5, fail_fast);
- b5 = static_bounds<size_t, 34>();
+ b5 = static_bounds<34>();
b6 = b5;
CHECK(b5 == b6);