diff --git a/README.md b/README.md index a32e89f..7d96dec 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ The test suite that exercises GSL has been built and passes successfully on the * GNU/Linux using GCC 5.1 * OS X Yosemite using Xcode with AppleClang 7.0.0.7000072 * OS X Yosemite using GCC-5.2.0 +* FreeBSD 10.x with Clang/LLVM 3.6 > If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider contributing any changes that were necessary back to this project to benefit the wider community. diff --git a/include/array_view.h b/include/array_view.h index 006f18c..ca4f897 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_ARRAY_VIEW_H +#define GSL_ARRAY_VIEW_H + #include #include #include @@ -27,10 +30,9 @@ #include #include "fail_fast.h" -#ifndef _MSC_VER -#define _CONSTEXPR constexpr -#else -#define _CONSTEXPR +#if defined(_MSC_VER) +#pragma push_macro("constexpr") +#define constexpr /* nothing */ #endif #pragma push_macro("_NOEXCEPT") @@ -71,53 +73,53 @@ namespace details }; - template + template class coordinate_facade { static_assert(std::is_integral::value && sizeof(ValueType) <= sizeof(size_t), "ValueType must be unsigned integral type!"); static_assert(Rank > 0, "Rank must be greater than 0!"); - template + template friend class coordinate_facade; public: using reference = ValueType&; using const_reference = const ValueType&; using value_type = ValueType; - static const unsigned int rank = Rank; - _CONSTEXPR coordinate_facade() _NOEXCEPT + static const size_t rank = Rank; + constexpr coordinate_facade() _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); } - _CONSTEXPR coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT + constexpr coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] = values[i]; } - _CONSTEXPR coordinate_facade(value_type e0) _NOEXCEPT + constexpr coordinate_facade(value_type e0) _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); static_assert(rank == 1, "This constructor can only be used with rank == 1."); elems[0] = e0; } // Preconditions: il.size() == rank - _CONSTEXPR coordinate_facade(std::initializer_list il) + constexpr coordinate_facade(std::initializer_list il) { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); fail_fast_assert(il.size() == rank, "The size of the initializer list must match the rank of the array"); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { elems[i] = begin(il)[i]; } } - _CONSTEXPR coordinate_facade(const coordinate_facade & other) = default; + constexpr coordinate_facade(const coordinate_facade & other) = default; template - _CONSTEXPR coordinate_facade(const coordinate_facade & other) + constexpr coordinate_facade(const coordinate_facade & other) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { fail_fast_assert(static_cast(other.elems[i]) <= SizeTypeTraits::max_value); elems[i] = static_cast(other.elems[i]); @@ -126,126 +128,126 @@ namespace details protected: coordinate_facade& operator=(const coordinate_facade& rhs) = default; // Preconditions: component_idx < rank - _CONSTEXPR reference operator[](unsigned int component_idx) + constexpr reference operator[](size_t component_idx) { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } // Preconditions: component_idx < rank - _CONSTEXPR const_reference operator[](unsigned int component_idx) const + constexpr const_reference operator[](size_t component_idx) const { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } - _CONSTEXPR bool operator==(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator==(const ConcreteType& rhs) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (elems[i] != rhs.elems[i]) return false; } return true; } - _CONSTEXPR bool operator!=(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator!=(const ConcreteType& rhs) const _NOEXCEPT { return !(to_concrete() == rhs); } - _CONSTEXPR ConcreteType operator+() const _NOEXCEPT + constexpr ConcreteType operator+() const _NOEXCEPT { return to_concrete(); } - _CONSTEXPR ConcreteType operator-() const + constexpr ConcreteType operator-() const { ConcreteType ret = to_concrete(); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret.elems[i] = -ret.elems[i]; return ret; } - _CONSTEXPR ConcreteType operator+(const ConcreteType& rhs) const + constexpr ConcreteType operator+(const ConcreteType& rhs) const { ConcreteType ret = to_concrete(); ret += rhs; return ret; } - _CONSTEXPR ConcreteType operator-(const ConcreteType& rhs) const + constexpr ConcreteType operator-(const ConcreteType& rhs) const { ConcreteType ret = to_concrete(); ret -= rhs; return ret; } - _CONSTEXPR ConcreteType& operator+=(const ConcreteType& rhs) + constexpr ConcreteType& operator+=(const ConcreteType& rhs) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] += rhs.elems[i]; return to_concrete(); } - _CONSTEXPR ConcreteType& operator-=(const ConcreteType& rhs) + constexpr ConcreteType& operator-=(const ConcreteType& rhs) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] -= rhs.elems[i]; return to_concrete(); } - _CONSTEXPR ConcreteType& operator++() + constexpr ConcreteType& operator++() { static_assert(rank == 1, "This operator can only be used with rank == 1."); ++elems[0]; return to_concrete(); } - _CONSTEXPR ConcreteType operator++(int) + constexpr ConcreteType operator++(int) { static_assert(rank == 1, "This operator can only be used with rank == 1."); ConcreteType ret = to_concrete(); ++(*this); return ret; } - _CONSTEXPR ConcreteType& operator--() + constexpr ConcreteType& operator--() { static_assert(rank == 1, "This operator can only be used with rank == 1."); --elems[0]; return to_concrete(); } - _CONSTEXPR ConcreteType operator--(int) + constexpr ConcreteType operator--(int) { static_assert(rank == 1, "This operator can only be used with rank == 1."); ConcreteType ret = to_concrete(); --(*this); return ret; } - _CONSTEXPR ConcreteType operator*(value_type v) const + constexpr ConcreteType operator*(value_type v) const { ConcreteType ret = to_concrete(); ret *= v; return ret; } - _CONSTEXPR ConcreteType operator/(value_type v) const + constexpr ConcreteType operator/(value_type v) const { ConcreteType ret = to_concrete(); ret /= v; return ret; } - friend _CONSTEXPR ConcreteType operator*(value_type v, const ConcreteType& rhs) + friend constexpr ConcreteType operator*(value_type v, const ConcreteType& rhs) { return rhs * v; } - _CONSTEXPR ConcreteType& operator*=(value_type v) + constexpr ConcreteType& operator*=(value_type v) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] *= v; return to_concrete(); } - _CONSTEXPR ConcreteType& operator/=(value_type v) + constexpr ConcreteType& operator/=(value_type v) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] /= v; return to_concrete(); } value_type elems[rank] = {}; private: - _CONSTEXPR const ConcreteType& to_concrete() const _NOEXCEPT + constexpr const ConcreteType& to_concrete() const _NOEXCEPT { return static_cast(*this); } - _CONSTEXPR ConcreteType& to_concrete() _NOEXCEPT + constexpr ConcreteType& to_concrete() _NOEXCEPT { return static_cast(*this); } @@ -270,12 +272,12 @@ namespace details }; } -template +template class index : private details::coordinate_facade, ValueType, Rank> { using Base = details::coordinate_facade, ValueType, Rank>; friend Base; - template + template friend class index; public: using Base::rank; @@ -283,17 +285,17 @@ public: using const_reference = typename Base::const_reference; using size_type = typename Base::value_type; using value_type = typename Base::value_type; - _CONSTEXPR index() _NOEXCEPT : Base(){} - _CONSTEXPR index(const value_type (&values)[rank]) _NOEXCEPT : Base(values) {} - _CONSTEXPR index(std::initializer_list il) : Base(il) {} + constexpr index() _NOEXCEPT : Base(){} + constexpr index(const value_type (&values)[rank]) _NOEXCEPT : Base(values) {} + constexpr index(std::initializer_list il) : Base(il) {} - _CONSTEXPR index(const index &) = default; + constexpr index(const index &) = default; template - _CONSTEXPR index(const index &other) : Base(other) + constexpr index(const index &other) : Base(other) { } - _CONSTEXPR static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) _NOEXCEPT { value_type (&arr)[rank] = (value_type(&)[rank])(*(other.elems + 1)); return index(arr); @@ -317,133 +319,133 @@ public: template class index<1, ValueType> { - template + template friend class index; public: - static const unsigned int rank = 1; + static const size_t rank = 1; using reference = ValueType&; using const_reference = const ValueType&; using size_type = ValueType; using value_type = ValueType; - _CONSTEXPR index() _NOEXCEPT : value(0) + constexpr index() _NOEXCEPT : value(0) { } - _CONSTEXPR index(value_type e0) _NOEXCEPT : value(e0) + constexpr index(value_type e0) _NOEXCEPT : value(e0) { } - _CONSTEXPR index(const value_type(&values)[1]) _NOEXCEPT : index(values[0]) + constexpr index(const value_type(&values)[1]) _NOEXCEPT : index(values[0]) { } // Preconditions: il.size() == rank - _CONSTEXPR index(std::initializer_list il) + constexpr index(std::initializer_list il) { fail_fast_assert(il.size() == rank, "Size of the initializer list must match the rank of the array"); value = begin(il)[0]; } - _CONSTEXPR index(const index &) = default; + constexpr index(const index &) = default; template - _CONSTEXPR index(const index<1, OtherValueType> & other) + constexpr index(const index<1, OtherValueType> & other) { fail_fast_assert(other.value <= details::SizeTypeTraits::max_value); value = static_cast(other.value); } - _CONSTEXPR static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) _NOEXCEPT { return other.elems[1]; } // Preconditions: component_idx < rank - _CONSTEXPR reference operator[](size_type component_idx) _NOEXCEPT + 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 < rank - _CONSTEXPR const_reference operator[](size_type component_idx) const _NOEXCEPT + 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 + constexpr bool operator==(const index& rhs) const _NOEXCEPT { return value == rhs.value; } - _CONSTEXPR bool operator!=(const index& rhs) const _NOEXCEPT + 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 index(rhs * v); } @@ -537,8 +539,8 @@ namespace details template struct BoundsRanges { - static const unsigned int Depth = 0; - static const unsigned int DynamicNum = 0; + static const size_t Depth = 0; + static const size_t DynamicNum = 0; static const SizeType CurrentRange = 1; static const SizeType TotalSize = 1; @@ -546,19 +548,19 @@ namespace details // TODO : following signature is for work around VS bug template - BoundsRanges (const OtherType &, bool firstLevel) {} + BoundsRanges (const OtherType &, bool /* firstLevel */) {} BoundsRanges(const SizeType * const) { } BoundsRanges() = default; - template + template void serialize(T &) const { } - template + template SizeType linearize(const T &) const { return 0; } - template + template ptrdiff_t contains(const T &) const { return 0; } @@ -576,8 +578,8 @@ namespace details template struct BoundsRanges : BoundsRanges{ using Base = BoundsRanges ; - static const unsigned int Depth = Base::Depth + 1; - static const unsigned int DynamicNum = Base::DynamicNum + 1; + 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; @@ -591,24 +593,24 @@ namespace details BoundsRanges() : m_bound(0) {} template - BoundsRanges(const BoundsRanges &other, bool firstLevel = true) : + BoundsRanges(const BoundsRanges &other, bool /* firstLevel */ = true) : Base(static_cast&>(other), false), m_bound (static_cast(other.totalSize())) { } - template + template void serialize(T & arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); } - template + template SizeType linearize(const T & arr) const { const size_t index = this->Base::totalSize() * arr[Dim]; fail_fast_assert(index < static_cast(m_bound)); return static_cast(index) + this->Base::template linearize(arr); } - template + template ptrdiff_t contains(const T & arr) const { const ptrdiff_t last = this->Base::template contains(arr); if (last == -1) @@ -625,7 +627,7 @@ namespace details return static_cast(totalSize() / this->Base::totalSize()); } - SizeType elementNum(unsigned int dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const _NOEXCEPT{ if (dim > 0) return this->Base::elementNum(dim - 1); else @@ -641,8 +643,8 @@ namespace details template struct BoundsRanges : BoundsRanges{ using Base = BoundsRanges ; - static const unsigned int Depth = Base::Depth + 1; - static const unsigned int DynamicNum = Base::DynamicNum; + static const size_t Depth = Base::Depth + 1; + static const size_t DynamicNum = Base::DynamicNum; static const SizeType CurrentRange = static_cast(CurRange); static const SizeType TotalSize = StaticSizeHelper::value; static_assert (CurRange <= SizeTypeTraits::max_value, "CurRange must be smaller than SizeType limits"); @@ -657,19 +659,19 @@ namespace details fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize()); } - template + template void serialize(T & arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); } - template + template SizeType linearize(const T & arr) const { fail_fast_assert(arr[Dim] < CurrentRange, "Index is out of range"); return static_cast(this->Base::totalSize()) * arr[Dim] + this->Base::template linearize(arr); } - template + template ptrdiff_t contains(const T & arr) const { if (static_cast(arr[Dim]) >= CurrentRange) return -1; @@ -687,7 +689,7 @@ namespace details return CurrentRange; } - SizeType elementNum(unsigned int dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const _NOEXCEPT{ if (dim > 0) return this->Base::elementNum(dim - 1); else @@ -732,17 +734,17 @@ namespace details { const TypeChain & obj; TypeListIndexer(const TypeChain & obj) :obj(obj){} - template + template const TypeChain & getObj(std::true_type) { return obj; } - template + template auto getObj(std::false_type) -> decltype(TypeListIndexer(static_cast(obj)).template get()) { return TypeListIndexer(static_cast(obj)).template get(); } - template + template auto get() -> decltype(getObj(std::integral_constant())) { return getObj(std::integral_constant()); @@ -762,7 +764,7 @@ class bounds_iterator; template class static_bounds { public: - static_bounds(const details::BoundsRanges &empty) { + static_bounds(const details::BoundsRanges &) { } }; @@ -774,13 +776,13 @@ class static_bounds && details::SizeTypeTraits::max_value <= SIZE_MAX, "SizeType must be an integral type and its numeric limits must be smaller than SIZE_MAX"); MyRanges m_ranges; - _CONSTEXPR static_bounds(const MyRanges & range) : m_ranges(range) { } + constexpr static_bounds(const MyRanges & range) : m_ranges(range) { } template friend class static_bounds; public: - static const unsigned int rank = MyRanges::Depth; - static const unsigned int dynamic_rank = MyRanges::DynamicNum; + static const size_t rank = MyRanges::Depth; + static const size_t dynamic_rank = MyRanges::DynamicNum; static const SizeType static_size = static_cast(MyRanges::TotalSize); using size_type = SizeType; @@ -791,72 +793,72 @@ public: using sliced_type = static_bounds; using mapping_type = contiguous_mapping_tag; public: - _CONSTEXPR static_bounds(const static_bounds &) = default; + constexpr static_bounds(const static_bounds &) = default; template , details::BoundsRanges >::value>> - _CONSTEXPR static_bounds(const static_bounds &other): + constexpr static_bounds(const static_bounds &other): m_ranges(other.m_ranges) { } - _CONSTEXPR static_bounds(std::initializer_list il) : m_ranges(il.begin()) + constexpr static_bounds(std::initializer_list 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::max_value, "Size of the range is larger than the max element of the size type"); } - _CONSTEXPR static_bounds() = default; + 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; } - _CONSTEXPR sliced_type slice() const _NOEXCEPT + constexpr sliced_type slice() const _NOEXCEPT { return sliced_type{static_cast &>(m_ranges)}; } - _CONSTEXPR size_type stride() const _NOEXCEPT + constexpr size_type stride() const _NOEXCEPT { return rank > 1 ? slice().size() : 1; } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { return static_cast(m_ranges.totalSize()); } - _CONSTEXPR size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const _NOEXCEPT { return static_cast(m_ranges.totalSize()); } - _CONSTEXPR size_type linearize(const index_type & idx) const + constexpr size_type linearize(const index_type & idx) const { return m_ranges.linearize(idx); } - _CONSTEXPR bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const _NOEXCEPT { return m_ranges.contains(idx) != -1; } - _CONSTEXPR size_type operator[](unsigned int index) const _NOEXCEPT + constexpr size_type operator[](size_t index) const _NOEXCEPT { return m_ranges.elementNum(index); } - template - _CONSTEXPR size_type extent() const _NOEXCEPT + template + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return details::createTypeListIndexer(m_ranges).template get().elementNum(); } - _CONSTEXPR index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const _NOEXCEPT { index_type extents; m_ranges.serialize(extents); @@ -864,23 +866,23 @@ public: } template - _CONSTEXPR bool operator == (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator == (const static_bounds & rhs) const _NOEXCEPT { return this->size() == rhs.size(); } template - _CONSTEXPR bool operator != (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator != (const static_bounds & rhs) const _NOEXCEPT { return !(*this == rhs); } - _CONSTEXPR const_iterator begin() const _NOEXCEPT + constexpr const_iterator begin() const _NOEXCEPT { return const_iterator(*this); } - _CONSTEXPR const_iterator end() const _NOEXCEPT + constexpr const_iterator end() const _NOEXCEPT { index_type boundary; m_ranges.serialize(boundary); @@ -888,12 +890,12 @@ public: } }; -template +template class strided_bounds : private details::coordinate_facade, SizeType, Rank> { using Base = details::coordinate_facade, SizeType, Rank>; friend Base; - template + template friend class strided_bounds; public: @@ -910,77 +912,77 @@ public: static const size_t static_size = dynamic_range; using sliced_type = std::conditional_t, void>; using mapping_type = generalized_mapping_tag; - _CONSTEXPR strided_bounds(const strided_bounds &) = default; + constexpr strided_bounds(const strided_bounds &) = default; template - _CONSTEXPR strided_bounds(const strided_bounds &other) + constexpr strided_bounds(const strided_bounds &other) : Base(other), m_strides(other.strides) { } - _CONSTEXPR strided_bounds(const index_type &extents, const index_type &strides) + constexpr strided_bounds(const index_type &extents, const index_type &strides) : m_strides(strides) { - for (unsigned int i = 0; i < rank; i++) + for (size_t i = 0; i < rank; i++) Base::elems[i] = extents[i]; } - _CONSTEXPR strided_bounds(const value_type(&values)[rank], index_type strides) + constexpr strided_bounds(const value_type(&values)[rank], index_type strides) : Base(values), m_strides(std::move(strides)) { } - _CONSTEXPR index_type strides() const _NOEXCEPT + constexpr index_type strides() const _NOEXCEPT { return m_strides; } - _CONSTEXPR size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const _NOEXCEPT { size_type ret = 0; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret += (Base::elems[i] - 1) * m_strides[i]; return ret + 1; } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { size_type ret = 1; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret *= Base::elems[i]; return ret; } - _CONSTEXPR bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (idx[i] < 0 || idx[i] >= Base::elems[i]) return false; } return true; } - _CONSTEXPR size_type linearize(const index_type & idx) const + constexpr size_type linearize(const index_type & idx) const { size_type ret = 0; - for (unsigned int i = 0; i < rank; i++) + for (size_t i = 0; i < rank; i++) { fail_fast_assert(idx[i] < Base::elems[i], "index is out of bounds of the array"); ret += idx[i] * m_strides[i]; } return ret; } - _CONSTEXPR size_type stride() const _NOEXCEPT + constexpr size_type stride() const _NOEXCEPT { return m_strides[0]; } template 1), typename Ret = std::enable_if_t> - _CONSTEXPR sliced_type slice() const + constexpr sliced_type slice() const { return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; } - template - _CONSTEXPR size_type extent() const _NOEXCEPT + template + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); return Base::elems[Dim]; } - _CONSTEXPR index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const _NOEXCEPT { return index_type(Base::elems); } @@ -1000,7 +1002,7 @@ template struct is_bounds : std::integral_constant {}; template struct is_bounds> : std::integral_constant {}; -template +template struct is_bounds> : std::integral_constant {}; template @@ -1014,7 +1016,7 @@ class bounds_iterator private: using Base = std::iterator , const IndexType>; public: - static const unsigned int rank = IndexType::rank; + static const size_t rank = IndexType::rank; using typename Base::reference; using typename Base::pointer; using typename Base::difference_type; @@ -1038,7 +1040,7 @@ public: } bounds_iterator& operator++() _NOEXCEPT { - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { if (++curr[i] < boundary[i]) { @@ -1050,7 +1052,7 @@ public: } } // If we're here we've wrapped over - set to past-the-end. - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { curr[i] = boundary[i]; } @@ -1064,7 +1066,7 @@ public: } bounds_iterator& operator--() _NOEXCEPT { - for (int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { if (curr[i]-- > 0) { @@ -1096,11 +1098,11 @@ public: auto linear_idx = linearize(curr) + n; value_type stride; stride[rank - 1] = 1; - for (unsigned int i = rank - 1; i-- > 0;) + for (size_t i = rank - 1; i-- > 0;) { stride[i] = stride[i + 1] * boundary[i + 1]; } - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { curr[i] = linear_idx / stride[i]; linear_idx = linear_idx % stride[i]; @@ -1134,7 +1136,7 @@ public: } bool operator<(const bounds_iterator& rhs) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (curr[i] < rhs.curr[i]) return true; @@ -1164,7 +1166,7 @@ private: // TODO: Smarter impl. // Check if past-the-end bool pte = true; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (idx[i] != boundary[i]) { @@ -1177,7 +1179,7 @@ private: if (pte) { res = 1; - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { res += (idx[i] - 1) * multiplier; multiplier *= boundary[i]; @@ -1185,7 +1187,7 @@ private: } else { - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { res += idx[i] * multiplier; multiplier *= boundary[i]; @@ -1320,20 +1322,20 @@ bounds_iterator operator+(typename bounds_iterator::differ namespace details { template - _CONSTEXPR std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT { return bnd.strides(); } - // Make a stride vector from bounds, assuming continugous memory. + // Make a stride vector from bounds, assuming contiguous memory. template - _CONSTEXPR std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT { auto extents = bnd.index_bounds(); typename Bounds::index_type stride; stride[Bounds::rank - 1] = 1; - for (int i = Bounds::rank - 2; i >= 0; --i) - stride[i] = stride[i + 1] * extents[i + 1]; + for (size_t i = Bounds::rank - 1; Bounds::rank > 1 && i > 0; --i) + stride[i-1] = stride[i] * extents[i]; return stride; } @@ -1359,7 +1361,7 @@ template class basic_array_view { public: - static const unsigned int rank = BoundsType::rank; + static const size_t rank = BoundsType::rank; using bounds_type = BoundsType; using size_type = typename bounds_type::size_type; using index_type = typename bounds_type::index_type; @@ -1377,30 +1379,30 @@ private: bounds_type m_bounds; public: - _CONSTEXPR bounds_type bounds() const _NOEXCEPT + constexpr bounds_type bounds() const _NOEXCEPT { return m_bounds; } - template - _CONSTEXPR size_type extent() const _NOEXCEPT + template + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return m_bounds.template extent(); } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { return m_bounds.size(); } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return m_pdata[m_bounds.linearize(idx)]; } - _CONSTEXPR pointer data() const _NOEXCEPT + constexpr pointer data() const _NOEXCEPT { return m_pdata; } template 1), typename Ret = std::enable_if_t> - _CONSTEXPR Ret operator[](size_type idx) const + constexpr Ret operator[](size_type idx) const { fail_fast_assert(idx < m_bounds.size(), "index is out of bounds of the array"); const size_type ridx = idx * m_bounds.stride(); @@ -1409,78 +1411,78 @@ public: return Ret {m_pdata + ridx, m_bounds.slice()}; } - _CONSTEXPR operator bool () const _NOEXCEPT + constexpr operator bool () const _NOEXCEPT { return m_pdata != nullptr; } - _CONSTEXPR iterator begin() const + constexpr iterator begin() const { return iterator {this, true}; } - _CONSTEXPR iterator end() const + constexpr iterator end() const { return iterator {this}; } - _CONSTEXPR const_iterator cbegin() const + constexpr const_iterator cbegin() const { return const_iterator {reinterpret_cast *>(this), true}; } - _CONSTEXPR const_iterator cend() const + constexpr const_iterator cend() const { return const_iterator {reinterpret_cast *>(this)}; } - _CONSTEXPR reverse_iterator rbegin() const + constexpr reverse_iterator rbegin() const { return reverse_iterator {end()}; } - _CONSTEXPR reverse_iterator rend() const + constexpr reverse_iterator rend() const { return reverse_iterator {begin()}; } - _CONSTEXPR const_reverse_iterator crbegin() const + constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator {cend()}; } - _CONSTEXPR const_reverse_iterator crend() const + constexpr const_reverse_iterator crend() const { return const_reverse_iterator {cbegin()}; } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator== (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator== (const basic_array_view & other) const _NOEXCEPT { return m_bounds.size() == other.m_bounds.size() && (m_pdata == other.m_pdata || std::equal(this->begin(), this->end(), other.begin())); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator!= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator!= (const basic_array_view & other) const _NOEXCEPT { return !(*this == other); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator< (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator< (const basic_array_view & other) const _NOEXCEPT { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator<= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator<= (const basic_array_view & other) const _NOEXCEPT { return !(other < *this); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator> (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator> (const basic_array_view & other) const _NOEXCEPT { return (other < *this); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator>= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator>= (const basic_array_view & other) const _NOEXCEPT { return !(*this < other); } @@ -1489,27 +1491,27 @@ public: template ::value && std::is_convertible::value>> - _CONSTEXPR basic_array_view(const basic_array_view & other ) _NOEXCEPT + constexpr basic_array_view(const basic_array_view & other ) _NOEXCEPT : m_pdata(other.m_pdata), m_bounds(other.m_bounds) { } protected: - _CONSTEXPR basic_array_view(pointer data, bounds_type bound) _NOEXCEPT + constexpr basic_array_view(pointer data, bounds_type bound) _NOEXCEPT : m_pdata(data) , m_bounds(std::move(bound)) { fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0); } template - _CONSTEXPR basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) _NOEXCEPT + constexpr basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) _NOEXCEPT : m_pdata(reinterpret_cast(data)) , m_bounds(std::move(bound)) { fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0); } template - _CONSTEXPR basic_array_view as_array_view(const DestBounds &bounds) + constexpr basic_array_view as_array_view(const DestBounds &bounds) { details::verifyBoundsReshape(m_bounds, bounds); return {m_pdata, bounds}; @@ -1537,7 +1539,7 @@ struct dim template class array_view; -template +template class strided_array_view; namespace details @@ -1616,7 +1618,7 @@ namespace details template struct is_array_view_oracle> : std::true_type {}; - template + template struct is_array_view_oracle> : std::true_type {}; template @@ -1658,22 +1660,22 @@ public: public: // basic - _CONSTEXPR array_view(pointer ptr, bounds_type bounds) : Base(ptr, std::move(bounds)) + 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) : Base(nullptr, bounds_type{}) { } - _CONSTEXPR array_view(std::nullptr_t, size_type size) : Base(nullptr, bounds_type{}) + constexpr array_view(std::nullptr_t, size_type size) : Base(nullptr, bounds_type{}) { fail_fast_assert(size == 0); } // default template > - _CONSTEXPR array_view() : Base(nullptr, bounds_type()) + constexpr array_view() : Base(nullptr, bounds_type()) { } @@ -1681,7 +1683,7 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value>> - _CONSTEXPR array_view(T * const & data, size_type size) : Base(data, typename Helper::bounds_type{size}) + constexpr array_view(T * const & data, size_type size) : Base(data, typename Helper::bounds_type{size}) { } @@ -1689,7 +1691,7 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value>> - _CONSTEXPR array_view (T (&arr)[N]) : Base(arr, typename Helper::bounds_type()) + constexpr array_view (T (&arr)[N]) : Base(arr, typename Helper::bounds_type()) { } @@ -1697,19 +1699,19 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value >> - _CONSTEXPR array_view(T(&arr)[N], size_type size) : Base(arr, typename Helper::bounds_type{ size }) + 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 , typename Base::bounds_type>::value>> - _CONSTEXPR array_view (std::array, N> & arr) : Base(arr.data(), static_bounds()) + constexpr array_view (std::array, N> & arr) : Base(arr.data(), static_bounds()) { } template , typename Base::bounds_type>::value && std::is_const::value>> - _CONSTEXPR array_view (const std::array, N> & arr) : Base(arr.data(), static_bounds()) + constexpr array_view (const std::array, N> & arr) : Base(arr.data(), static_bounds()) { } @@ -1718,7 +1720,7 @@ public: template ::value && details::LessThan::value>> // remove literal 0 case - _CONSTEXPR array_view (pointer begin, Ptr end) : Base(begin, details::newBoundsHelper(static_cast(end) - begin)) + constexpr array_view (pointer begin, Ptr end) : Base(begin, details::newBoundsHelper(static_cast(end) - begin)) { } @@ -1729,12 +1731,12 @@ public: && std::is_convertible, typename Base::bounds_type>::value && std::is_same().size(), *std::declval().data())>, DataType>::value> > - _CONSTEXPR array_view (Cont& cont) : Base(static_cast(cont.data()), details::newBoundsHelper(cont.size())) + constexpr array_view (Cont& cont) : Base(static_cast(cont.data()), details::newBoundsHelper(cont.size())) { } - _CONSTEXPR array_view(const array_view &) = default; + constexpr array_view(const array_view &) = default; // convertible template ::value_type, static_bounds::size_type, OtherDimensions...>>, typename Dummy = std::enable_if_t::value> > - _CONSTEXPR array_view(const array_view &av) : Base(static_cast::Base &>(av)) {} // static_cast is required + constexpr array_view(const array_view &av) : Base(static_cast::Base &>(av)) {} // static_cast is required // reshape template - _CONSTEXPR array_view as_array_view(Dimensions2... dims) + constexpr array_view 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::bounds_type; @@ -1757,7 +1759,7 @@ public: // to bytes array template ::value_type>>::value> - _CONSTEXPR auto as_bytes() const _NOEXCEPT -> + constexpr auto as_bytes() const _NOEXCEPT -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1765,7 +1767,7 @@ public: } template ::value_type>>::value> - _CONSTEXPR auto as_writeable_bytes() const _NOEXCEPT -> + constexpr auto as_writeable_bytes() const _NOEXCEPT -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1775,7 +1777,7 @@ public: // from bytes array template::value, typename Dummy = std::enable_if_t> - _CONSTEXPR auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::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"); @@ -1784,7 +1786,7 @@ public: } template::value, typename Dummy = std::enable_if_t> - _CONSTEXPR auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::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"); @@ -1794,79 +1796,79 @@ public: // section on linear space template - _CONSTEXPR array_view first() const _NOEXCEPT + constexpr array_view 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 first(size_type count) const _NOEXCEPT + constexpr array_view first(size_type count) const _NOEXCEPT { fail_fast_assert(count <= this->size()); return { this->data(), count }; } template - _CONSTEXPR array_view last() const _NOEXCEPT + constexpr array_view 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 last(size_type count) const _NOEXCEPT + constexpr array_view last(size_type count) const _NOEXCEPT { fail_fast_assert(count <= this->size()); return { this->data() + this->size() - count, count }; } template - _CONSTEXPR array_view sub() const _NOEXCEPT + constexpr array_view 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 sub(size_type offset, size_type count = dynamic_range) const _NOEXCEPT + constexpr array_view 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 }; } // size - _CONSTEXPR size_type length() const _NOEXCEPT + constexpr size_type length() const _NOEXCEPT { return this->size(); } - _CONSTEXPR size_type used_length() const _NOEXCEPT + constexpr size_type used_length() const _NOEXCEPT { return length(); } - _CONSTEXPR size_type bytes() const _NOEXCEPT + constexpr size_type bytes() const _NOEXCEPT { return sizeof(value_type) * this->size(); } - _CONSTEXPR size_type used_bytes() const _NOEXCEPT + constexpr size_type used_bytes() const _NOEXCEPT { return bytes(); } // section - _CONSTEXPR strided_array_view section(index_type origin, index_type extents) const + constexpr strided_array_view 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 {extents, details::make_stride(Base::bounds())} }; } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return Base::operator[](idx); } template 1), typename Dummy = std::enable_if_t> - _CONSTEXPR array_view operator[](size_type idx) const + constexpr array_view operator[](size_type idx) const { auto ret = Base::operator[](idx); return{ ret.data(), ret.bounds() }; @@ -1881,61 +1883,61 @@ public: }; template -_CONSTEXPR auto as_array_view(T * const & ptr, dim... args) -> array_view, Dimensions...> +constexpr auto as_array_view(T * const & ptr, dim... args) -> array_view, Dimensions...> { return {reinterpret_cast*>(ptr), details::static_as_array_view_helper>(args..., details::Sep{})}; } template -_CONSTEXPR auto as_array_view (T * arr, size_t len) -> typename details::ArrayViewArrayTraits::type +constexpr auto as_array_view (T * arr, size_t len) -> typename details::ArrayViewArrayTraits::type { return {arr, len}; } template -_CONSTEXPR auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits::type +constexpr auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits::type { return {arr}; } template -_CONSTEXPR array_view as_array_view(const std::array &arr) +constexpr array_view as_array_view(const std::array &arr) { return {arr}; } template -_CONSTEXPR array_view as_array_view(const std::array &&) = delete; +constexpr array_view as_array_view(const std::array &&) = delete; template -_CONSTEXPR array_view as_array_view(std::array &arr) +constexpr array_view as_array_view(std::array &arr) { return {arr}; } template -_CONSTEXPR array_view as_array_view(T *begin, T *end) +constexpr array_view as_array_view(T *begin, T *end) { return {begin, end}; } template -_CONSTEXPR auto as_array_view(Cont &arr) -> std::enable_if_t>::value, +constexpr auto as_array_view(Cont &arr) -> std::enable_if_t>::value, array_view, dynamic_range>> { return {arr.data(), arr.size()}; } template -_CONSTEXPR auto as_array_view(Cont &&arr) -> std::enable_if_t>::value, +constexpr auto as_array_view(Cont &&arr) -> std::enable_if_t>::value, array_view, dynamic_range>> = delete; -template +template class strided_array_view : public basic_array_view::value_type, strided_bounds::size_type>> { using Base = basic_array_view::value_type, strided_bounds::size_type>>; - template + template friend class strided_array_view; public: using Base::rank; @@ -1974,7 +1976,7 @@ public: typename OtherBaseType = basic_array_view::value_type, strided_bounds::size_type>>, typename Dummy = std::enable_if_t::value> > - _CONSTEXPR strided_array_view(const strided_array_view &av): Base(static_cast::Base &>(av)) // static_cast is required + constexpr strided_array_view(const strided_array_view &av): Base(static_cast::Base &>(av)) // static_cast is required { } @@ -1995,13 +1997,13 @@ public: return { &this->operator[](origin), size, bounds_type {extents, details::make_stride(Base::bounds())}}; } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return Base::operator[](idx); } template 1), typename Dummy = std::enable_if_t> - _CONSTEXPR strided_array_view operator[](size_type idx) const + constexpr strided_array_view operator[](size_type idx) const { auto ret = Base::operator[](idx); return{ ret.data(), ret.bounds().total_size(), ret.bounds() }; @@ -2019,7 +2021,7 @@ private: } template > - static index_type resize_stride(const index_type& strides, size_t d, void *p = 0) + static index_type resize_stride(const index_type& strides, size_t , void * = 0) { fail_fast_assert(strides[rank - 1] == 1, "Only strided arrays with regular strides can be resized"); @@ -2032,10 +2034,8 @@ private: fail_fast_assert(strides[rank - 1] == 1, "Only strided arrays with regular strides can be resized"); fail_fast_assert(strides[rank - 2] >= d && (strides[rank - 2] % d == 0), "The strides must have contiguous chunks of memory that can contain a multiple of new type elements"); - for (int i = rank - 2; i >= 0; --i) - { - fail_fast_assert((strides[i] >= strides[i + 1]) && (strides[i] % strides[i + 1] == 0), "Only strided arrays with regular strides can be resized"); - } + for (size_t i = rank - 1; i > 0; --i) + fail_fast_assert((strides[i-1] >= strides[i]) && (strides[i-1] % strides[i] == 0), "Only strided arrays with regular strides can be resized"); index_type ret = strides / d; ret[rank - 1] = 1; @@ -2281,8 +2281,15 @@ general_array_view_iterator operator+(typename general_array_view_ite } // namespace Guide +#if defined(_MSC_VER) +#undef constexpr +#pragma pop_macro("constexpr") +#endif + #if defined(_MSC_VER) && _MSC_VER <= 1800 #pragma warning(pop) #endif // _MSC_VER <= 1800 #pragma pop_macro("_NOEXCEPT") + +#endif // GSL_ARRAY_VIEW_H diff --git a/include/fail_fast.h b/include/fail_fast.h index dfd0ede..78a5102 100644 --- a/include/fail_fast.h +++ b/include/fail_fast.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_FAIL_FAST_H +#define GSL_FAIL_FAST_H + #include #include @@ -45,3 +48,5 @@ inline void fail_fast_assert(bool cond, const char* const) { if (!cond) std::ter #endif // SAFER_CPP_TESTING } + +#endif // GSL_FAIL_FAST_H diff --git a/include/gsl.h b/include/gsl.h index 009c777..1405993 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_GSL_H +#define GSL_GSL_H + #include "array_view.h" // array_view, strided_array_view... #include "string_view.h" // zstring, string_view, zstring_builder... #include @@ -47,7 +50,7 @@ template class Final_act { public: - explicit Final_act(F f) : f_(f) {} + explicit Final_act(F f) : f_(std::move(f)) {} Final_act(const Final_act&& other) : f_(other.f_) {} Final_act(const Final_act&) = delete; @@ -61,7 +64,10 @@ private: // finally() - convenience function to generate a Final_act template -Final_act finally(F f) { return Final_act(f); } +Final_act finally(const F &f) { return Final_act(f); } + +template +Final_act finally(F &&f) { return Final_act(std::forward(f)); } // narrow_cast(): a searchable way to do narrowing casts of values template @@ -102,23 +108,30 @@ typename Cont::value_type& at(Cont& cont, size_t index) { fail_fast_assert(index template class not_null { + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: not_null(T t) : ptr_(t) { ensure_invariant(); } - - // deleting these two prevents compilation when initialized with a nullptr or literal 0 - not_null(std::nullptr_t) = delete; - not_null(int) = delete; + not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; } not_null(const not_null &other) = default; + not_null& operator=(const not_null &other) = default; template ::value>> - not_null(const not_null &other) : ptr_(other.get()) + not_null(const not_null &other) { + *this = other; } - not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; } + template ::value>> + not_null& operator=(const not_null &other) + { + ptr_ = other.get(); + return *this; + } // prevents compilation when someone attempts to assign a nullptr + not_null(std::nullptr_t) = delete; + not_null(int) = delete; not_null& operator=(std::nullptr_t) = delete; not_null& operator=(int) = delete; @@ -159,29 +172,21 @@ private: // // Describes an optional pointer - provides symmetry with not_null // +template +class maybe_null_ret; + template class maybe_null_dbg { template friend class maybe_null_dbg; -public: - static_assert(std::is_constructible::value, "maybe_null's template parameter must be constructible from nullptr"); + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); +public: maybe_null_dbg() : ptr_(nullptr), tested_(false) {} + maybe_null_dbg(std::nullptr_t) : ptr_(nullptr), tested_(false) {} maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {} - maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {} - - template ::value>> - maybe_null_dbg(const not_null &other) : ptr_(other.get()), tested_(false) - { - } - - template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) - { - } - maybe_null_dbg& operator=(const T& p) { if (ptr_ != p) @@ -192,6 +197,8 @@ public: return *this; } + + maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {} maybe_null_dbg& operator=(const maybe_null_dbg& rhs) { if (this != &rhs) @@ -202,6 +209,43 @@ public: return *this; } + + template ::value>> + maybe_null_dbg(const not_null &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const not_null &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + + template ::value>> + maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const maybe_null_dbg &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + + template ::value>> + maybe_null_dbg(const maybe_null_ret &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const maybe_null_ret &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + bool present() const { tested_ = true; return ptr_ != nullptr; } bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; } @@ -241,34 +285,49 @@ private: template class maybe_null_ret { + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: - static_assert(std::is_constructible::value, "maybe_null's template parameter must be constructible from nullptr"); - maybe_null_ret() : ptr_(nullptr) {} maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} + maybe_null_ret(const T& p) : ptr_(p) {} + maybe_null_ret& operator=(const T& p) { ptr_ = p; return *this; } + maybe_null_ret(const maybe_null_ret& rhs) = default; - - template ::value>> - maybe_null_ret(const not_null &other) : ptr_(other.get()) - { - } - - template ::value>> - maybe_null_ret(const maybe_null_ret &other) : ptr_(other.get()) - { - } - - template ::value>> - maybe_null_ret(const maybe_null_dbg &other) : ptr_(other.get()) - { - } - - maybe_null_ret& operator=(const T& p) { if (ptr_ != p) { ptr_ = p; } return *this; } maybe_null_ret& operator=(const maybe_null_ret& rhs) = default; - bool operator==(const T& rhs) const { return ptr_ == rhs; } - bool operator!=(const T& rhs) const { return ptr_ != rhs; } + template ::value>> + maybe_null_ret(const not_null &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const not_null &other) + { + ptr_ = other.get(); + return *this; + } + + + template ::value>> + maybe_null_ret(const maybe_null_ret &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const maybe_null_ret &other) + { + ptr_ = other.get(); + return *this; + } + + + template ::value>> + maybe_null_ret(const maybe_null_dbg &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const maybe_null_dbg &other) + { + ptr_ = other.get(); + return *this; + } + bool present() const { return ptr_ != nullptr; } @@ -295,3 +354,5 @@ private: template using maybe_null = maybe_null_ret; } // namespace Guide + +#endif // GSL_GSL_H diff --git a/include/string_view.h b/include/string_view.h index 7becc8e..e683c7a 100644 --- a/include/string_view.h +++ b/include/string_view.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_STRING_VIEW_H +#define GSL_STRING_VIEW_H + #include "array_view.h" #include @@ -176,3 +179,5 @@ using zstring_builder = basic_zstring_builder; template using wzstring_builder = basic_zstring_builder; } + +#endif // GSL_STRING_VIEW_H diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index e1244fd..d6b53f0 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include using namespace Guide; @@ -27,12 +29,24 @@ SUITE(MaybeNullTests) { TEST(TestMaybeNull1) { +#ifdef CONFIRM_COMPILATION_ERRORS + // Forbid non-nullptr assignable types + maybe_null_ret> f_ret(std::vector{1}); + maybe_null_ret> f_ret(std::vector{1}); + maybe_null_ret z_ret(10); + maybe_null_dbg> y_dbg({1,2}); + maybe_null_dbg z_dbg(10); + maybe_null_dbg> y_dbg({1,2}); +#endif int n = 5; maybe_null_dbg opt_n(&n); int result = 0; bool threw = false; CHECK_THROW(result = *opt_n, fail_fast); + + maybe_null_ret> x_ret(std::make_shared(10)); // shared_ptr is nullptr assignable + maybe_null_dbg> x_dbg(std::make_shared(10)); // shared_ptr is nullptr assignable } TEST(TestMaybeNull2) @@ -242,18 +256,41 @@ SUITE(MaybeNullTests) CHECK(p1.get() != nullptr); } - TEST(TestMaybeNullPtrT) + TEST(TestMaybeNullAssignmentOps) { - maybe_null p1; - maybe_null p2; + MyBase base; + MyDerived derived; + Unrelated unrelated; - CHECK_THROW(p1.get(), fail_fast); + not_null nnBase(&base); + not_null nnDerived(&derived); + not_null nnUnrelated(&unrelated); - CHECK(p1 == p2); + maybe_null_ret mnBase_ret1(&base), mnBase_ret2; + mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret + mnBase_ret2 = nnBase; // maybe_null_ret = not_null - // Make sure we no longer throw here - CHECK(p1.get() == nullptr); - CHECK(p2.get() == nullptr); + maybe_null_ret mnDerived_ret(&derived); + mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret + mnBase_ret1 = &derived; // maybe_null_ret = U; + mnBase_ret1 = nnDerived; // maybe_null_ret = not_null + + maybe_null_ret mnUnrelated_ret; + mnUnrelated_ret = &unrelated; // maybe_null_ret = T + + maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; + mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg + mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null + + maybe_null_dbg mnDerived_dbg(&derived); + CHECK(mnDerived_dbg.present()); + mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg + + mnBase_dbg1 = &derived; // maybe_null_dbg = U; + mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null + + maybe_null_dbg mnUnrelated_dbg; + mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T } } diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 008cbb3..46011b6 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -16,6 +16,7 @@ #include #include +#include using namespace Guide; @@ -48,21 +49,35 @@ SUITE(NotNullTests) not_null p; // yay...does not compile! std::unique_ptr up = std::make_unique(120); not_null p = up; + + // Forbid non-nullptr assignable types + not_null> f(std::vector{1}); + not_null z(10); + not_null> y({1,2}); #endif int i = 12; auto rp = RefCounted(&i); not_null p(rp); CHECK(p.get() == &i); + + not_null> x(std::make_shared(10)); // shared_ptr is nullptr assignable } TEST(TestNotNullCasting) { - MyDerived derived; + MyBase base; + MyDerived derived; + Unrelated unrelated; + not_null u = &unrelated; not_null p = &derived; - not_null q = p; + not_null q = &base; + q = p; // allowed with heterogeneous copy ctor CHECK(q == p); #ifdef CONFIRM_COMPILATION_ERRORS + q = u; // no viable conversion possible between MyBase* and Unrelated* + p = q; // not possible to implicitly convert MyBase* to MyDerived* + not_null r = p; not_null s = reinterpret_cast(p); #endif diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 430b31a..d985533 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -33,6 +33,7 @@ SUITE(owner_tests) CHECK(*p == 120); f(p); CHECK(*p == 121); + delete p; } }