Merging Microsoft/GSL:master.

This commit is contained in:
Kern Handa 2015-09-27 21:37:32 +00:00
commit 3b088614bc
6 changed files with 122 additions and 75 deletions

View File

@ -16,6 +16,9 @@
#pragma once #pragma once
#ifndef GSL_ARRAY_VIEW_H
#define GSL_ARRAY_VIEW_H
#include <new> #include <new>
#include <stdexcept> #include <stdexcept>
#include <cstddef> #include <cstddef>
@ -71,20 +74,20 @@ namespace details
}; };
template <typename ConcreteType, typename ValueType, unsigned int Rank> template <typename ConcreteType, typename ValueType, size_t Rank>
class coordinate_facade class coordinate_facade
{ {
static_assert(std::is_integral<ValueType>::value static_assert(std::is_integral<ValueType>::value
&& sizeof(ValueType) <= sizeof(size_t), "ValueType must be unsigned integral type!"); && sizeof(ValueType) <= sizeof(size_t), "ValueType must be unsigned integral type!");
static_assert(Rank > 0, "Rank must be greater than 0!"); static_assert(Rank > 0, "Rank must be greater than 0!");
template <typename OtherConcreteType, typename OtherValueType, unsigned int OtherRank> template <typename OtherConcreteType, typename OtherValueType, size_t OtherRank>
friend class coordinate_facade; friend class coordinate_facade;
public: public:
using value_type = typename std::remove_reference<ValueType>::type; using value_type = typename std::remove_reference<ValueType>::type;
using reference = typename std::add_lvalue_reference<value_type>::type; using reference = typename std::add_lvalue_reference<value_type>::type;
using const_reference = typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type; using const_reference = typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type;
static const unsigned int rank = Rank; static const size_t rank = Rank;
_CONSTEXPR coordinate_facade() _NOEXCEPT _CONSTEXPR coordinate_facade() _NOEXCEPT
{ {
static_assert(std::is_base_of<coordinate_facade, ConcreteType>::value, "ConcreteType must be derived from coordinate_facade."); static_assert(std::is_base_of<coordinate_facade, ConcreteType>::value, "ConcreteType must be derived from coordinate_facade.");
@ -92,7 +95,7 @@ namespace details
_CONSTEXPR coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT _CONSTEXPR coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT
{ {
static_assert(std::is_base_of<coordinate_facade, ConcreteType>::value, "ConcreteType must be derived from coordinate_facade."); static_assert(std::is_base_of<coordinate_facade, ConcreteType>::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]; elems[i] = values[i];
} }
_CONSTEXPR coordinate_facade(value_type e0) _NOEXCEPT _CONSTEXPR coordinate_facade(value_type e0) _NOEXCEPT
@ -106,7 +109,7 @@ namespace details
{ {
static_assert(std::is_base_of<coordinate_facade, ConcreteType>::value, "ConcreteType must be derived from coordinate_facade."); static_assert(std::is_base_of<coordinate_facade, ConcreteType>::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"); 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]; elems[i] = begin(il)[i];
} }
@ -117,7 +120,7 @@ namespace details
template <typename OtherConcreteType, typename OtherValueType> template <typename OtherConcreteType, typename OtherValueType>
_CONSTEXPR coordinate_facade(const coordinate_facade<OtherConcreteType, OtherValueType, Rank> & other) _CONSTEXPR coordinate_facade(const coordinate_facade<OtherConcreteType, OtherValueType, Rank> & other)
{ {
for (unsigned int i = 0; i < rank; ++i) for (size_t i = 0; i < rank; ++i)
{ {
fail_fast_assert(static_cast<size_t>(other.elems[i]) <= SizeTypeTraits<value_type>::max_value); fail_fast_assert(static_cast<size_t>(other.elems[i]) <= SizeTypeTraits<value_type>::max_value);
elems[i] = static_cast<value_type>(other.elems[i]); elems[i] = static_cast<value_type>(other.elems[i]);
@ -126,20 +129,20 @@ namespace details
protected: protected:
coordinate_facade& operator=(const coordinate_facade& rhs) = default; coordinate_facade& operator=(const coordinate_facade& rhs) = default;
// Preconditions: component_idx < rank // 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"); fail_fast_assert(component_idx < rank, "Component index must be less than rank");
return elems[component_idx]; return elems[component_idx];
} }
// Preconditions: component_idx < rank // 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"); fail_fast_assert(component_idx < rank, "Component index must be less than rank");
return elems[component_idx]; 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]) if (elems[i] != rhs.elems[i])
return false; return false;
@ -157,7 +160,7 @@ namespace details
_CONSTEXPR ConcreteType operator-() const _CONSTEXPR ConcreteType operator-() const
{ {
ConcreteType ret = to_concrete(); 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]; ret.elems[i] = -ret.elems[i];
return ret; return ret;
} }
@ -175,13 +178,13 @@ namespace details
} }
_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]; elems[i] += rhs.elems[i];
return to_concrete(); 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]; elems[i] -= rhs.elems[i];
return to_concrete(); return to_concrete();
} }
@ -229,13 +232,13 @@ namespace details
} }
_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; elems[i] *= v;
return to_concrete(); 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; elems[i] /= v;
return to_concrete(); return to_concrete();
} }
@ -270,12 +273,12 @@ namespace details
}; };
} }
template <unsigned int Rank, typename ValueType = size_t> template <size_t Rank, typename ValueType = size_t>
class index : private details::coordinate_facade<index<Rank, ValueType>, ValueType, Rank> class index : private details::coordinate_facade<index<Rank, ValueType>, ValueType, Rank>
{ {
using Base = details::coordinate_facade<index<Rank, ValueType>, ValueType, Rank>; using Base = details::coordinate_facade<index<Rank, ValueType>, ValueType, Rank>;
friend Base; friend Base;
template <unsigned int OtherRank, typename OtherValueType> template <size_t OtherRank, typename OtherValueType>
friend class index; friend class index;
public: public:
using Base::rank; using Base::rank;
@ -317,10 +320,10 @@ public:
template <typename ValueType> template <typename ValueType>
class index<1, ValueType> class index<1, ValueType>
{ {
template <unsigned int, typename OtherValueType> template <size_t, typename OtherValueType>
friend class index; friend class index;
public: public:
static const unsigned int rank = 1; static const size_t rank = 1;
using reference = ValueType&; using reference = ValueType&;
using const_reference = const ValueType&; using const_reference = const ValueType&;
using size_type = ValueType; using size_type = ValueType;
@ -537,8 +540,8 @@ namespace details
template <typename SizeType, size_t... Ranges> template <typename SizeType, size_t... Ranges>
struct BoundsRanges { struct BoundsRanges {
static const unsigned int Depth = 0; static const size_t Depth = 0;
static const unsigned int DynamicNum = 0; static const size_t DynamicNum = 0;
static const SizeType CurrentRange = 1; static const SizeType CurrentRange = 1;
static const SizeType TotalSize = 1; static const SizeType TotalSize = 1;
@ -551,14 +554,14 @@ namespace details
BoundsRanges() = default; BoundsRanges() = default;
template <typename T, unsigned int Dim> template <typename T, size_t Dim>
void serialize(T &) const { void serialize(T &) const {
} }
template <typename T, unsigned int Dim> template <typename T, size_t Dim>
SizeType linearize(const T &) const { SizeType linearize(const T &) const {
return 0; return 0;
} }
template <typename T, unsigned int Dim> template <typename T, size_t Dim>
ptrdiff_t contains(const T &) const { ptrdiff_t contains(const T &) const {
return 0; return 0;
} }
@ -576,8 +579,8 @@ namespace details
template <typename SizeType, size_t... RestRanges> template <typename SizeType, size_t... RestRanges>
struct BoundsRanges <SizeType, dynamic_range, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{ struct BoundsRanges <SizeType, dynamic_range, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{
using Base = BoundsRanges <SizeType, RestRanges... >; using Base = BoundsRanges <SizeType, RestRanges... >;
static const unsigned int Depth = Base::Depth + 1; static const size_t Depth = Base::Depth + 1;
static const unsigned int DynamicNum = Base::DynamicNum + 1; static const size_t DynamicNum = Base::DynamicNum + 1;
static const SizeType CurrentRange = dynamic_range; static const SizeType CurrentRange = dynamic_range;
static const SizeType TotalSize = dynamic_range; static const SizeType TotalSize = dynamic_range;
const SizeType m_bound; const SizeType m_bound;
@ -596,19 +599,19 @@ namespace details
{ {
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
void serialize(T & arr) const { void serialize(T & arr) const {
arr[Dim] = elementNum(); arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr); this->Base::template serialize<T, Dim + 1>(arr);
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
SizeType linearize(const T & arr) const { SizeType linearize(const T & arr) const {
const size_t index = this->Base::totalSize() * arr[Dim]; const size_t index = this->Base::totalSize() * arr[Dim];
fail_fast_assert(index < static_cast<size_t>(m_bound)); fail_fast_assert(index < static_cast<size_t>(m_bound));
return static_cast<SizeType>(index) + this->Base::template linearize<T, Dim + 1>(arr); return static_cast<SizeType>(index) + this->Base::template linearize<T, Dim + 1>(arr);
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
ptrdiff_t contains(const T & arr) const { ptrdiff_t contains(const T & arr) const {
const ptrdiff_t last = this->Base::template contains<T, Dim + 1>(arr); const ptrdiff_t last = this->Base::template contains<T, Dim + 1>(arr);
if (last == -1) if (last == -1)
@ -625,7 +628,7 @@ namespace details
return static_cast<SizeType>(totalSize() / this->Base::totalSize()); return static_cast<SizeType>(totalSize() / this->Base::totalSize());
} }
SizeType elementNum(unsigned int dim) const _NOEXCEPT{ SizeType elementNum(size_t dim) const _NOEXCEPT{
if (dim > 0) if (dim > 0)
return this->Base::elementNum(dim - 1); return this->Base::elementNum(dim - 1);
else else
@ -641,8 +644,8 @@ namespace details
template <typename SizeType, size_t CurRange, size_t... RestRanges> template <typename SizeType, size_t CurRange, size_t... RestRanges>
struct BoundsRanges <SizeType, CurRange, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{ struct BoundsRanges <SizeType, CurRange, RestRanges...> : BoundsRanges<SizeType, RestRanges...>{
using Base = BoundsRanges <SizeType, RestRanges... >; using Base = BoundsRanges <SizeType, RestRanges... >;
static const unsigned int Depth = Base::Depth + 1; static const size_t Depth = Base::Depth + 1;
static const unsigned int DynamicNum = Base::DynamicNum; static const size_t DynamicNum = Base::DynamicNum;
static const SizeType CurrentRange = static_cast<SizeType>(CurRange); static const SizeType CurrentRange = static_cast<SizeType>(CurRange);
static const SizeType TotalSize = StaticSizeHelper<SizeType, Base::TotalSize, CurrentRange>::value; 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_assert (CurRange <= SizeTypeTraits<SizeType>::max_value, "CurRange must be smaller than SizeType limits");
@ -657,19 +660,19 @@ namespace details
fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize()); fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize());
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
void serialize(T & arr) const { void serialize(T & arr) const {
arr[Dim] = elementNum(); arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr); this->Base::template serialize<T, Dim + 1>(arr);
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
SizeType linearize(const T & arr) const { SizeType linearize(const T & arr) const {
fail_fast_assert(arr[Dim] < CurrentRange, "Index is out of range"); 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 static_cast<SizeType>(this->Base::totalSize()) * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr);
} }
template <typename T, unsigned int Dim = 0> template <typename T, size_t Dim = 0>
ptrdiff_t contains(const T & arr) const { ptrdiff_t contains(const T & arr) const {
if (static_cast<size_t>(arr[Dim]) >= CurrentRange) if (static_cast<size_t>(arr[Dim]) >= CurrentRange)
return -1; return -1;
@ -687,7 +690,7 @@ namespace details
return CurrentRange; return CurrentRange;
} }
SizeType elementNum(unsigned int dim) const _NOEXCEPT{ SizeType elementNum(size_t dim) const _NOEXCEPT{
if (dim > 0) if (dim > 0)
return this->Base::elementNum(dim - 1); return this->Base::elementNum(dim - 1);
else else
@ -732,17 +735,17 @@ namespace details
{ {
const TypeChain & obj; const TypeChain & obj;
TypeListIndexer(const TypeChain & obj) :obj(obj){} TypeListIndexer(const TypeChain & obj) :obj(obj){}
template<unsigned int N> template<size_t N>
const TypeChain & getObj(std::true_type) const TypeChain & getObj(std::true_type)
{ {
return obj; return obj;
} }
template<unsigned int N, typename MyChain = TypeChain, typename MyBase = typename MyChain::Base> template<size_t N, typename MyChain = TypeChain, typename MyBase = typename MyChain::Base>
auto getObj(std::false_type) -> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase &>(obj)).template get<N>()) auto getObj(std::false_type) -> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase &>(obj)).template get<N>())
{ {
return TypeListIndexer<MyBase>(static_cast<const MyBase &>(obj)).template get<N>(); return TypeListIndexer<MyBase>(static_cast<const MyBase &>(obj)).template get<N>();
} }
template <unsigned int N> template <size_t N>
auto get() -> decltype(getObj<N - 1>(std::integral_constant<bool, true>())) auto get() -> decltype(getObj<N - 1>(std::integral_constant<bool, true>()))
{ {
return getObj<N - 1>(std::integral_constant<bool, N == 0>()); return getObj<N - 1>(std::integral_constant<bool, N == 0>());
@ -779,8 +782,8 @@ class static_bounds<SizeType, FirstRange, RestRanges...>
template <typename SizeType2, size_t... Ranges2> template <typename SizeType2, size_t... Ranges2>
friend class static_bounds; friend class static_bounds;
public: public:
static const unsigned int rank = MyRanges::Depth; static const size_t rank = MyRanges::Depth;
static const unsigned int dynamic_rank = MyRanges::DynamicNum; static const size_t dynamic_rank = MyRanges::DynamicNum;
static const SizeType static_size = static_cast<SizeType>(MyRanges::TotalSize); static const SizeType static_size = static_cast<SizeType>(MyRanges::TotalSize);
using size_type = SizeType; using size_type = SizeType;
@ -844,12 +847,12 @@ public:
return m_ranges.contains(idx) != -1; 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); return m_ranges.elementNum(index);
} }
template <unsigned int Dim = 0> template <size_t Dim = 0>
_CONSTEXPR size_type extent() const _NOEXCEPT _CONSTEXPR size_type extent() const _NOEXCEPT
{ {
static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)");
@ -888,12 +891,12 @@ public:
} }
}; };
template <unsigned int Rank, typename SizeType = size_t> template <size_t Rank, typename SizeType = size_t>
class strided_bounds : private details::coordinate_facade<strided_bounds<Rank>, SizeType, Rank> class strided_bounds : private details::coordinate_facade<strided_bounds<Rank>, SizeType, Rank>
{ {
using Base = details::coordinate_facade<strided_bounds<Rank>, SizeType, Rank>; using Base = details::coordinate_facade<strided_bounds<Rank>, SizeType, Rank>;
friend Base; friend Base;
template <unsigned int OtherRank, typename OtherSizeType> template <size_t OtherRank, typename OtherSizeType>
friend class strided_bounds; friend class strided_bounds;
public: public:
@ -921,7 +924,7 @@ public:
_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) : m_strides(strides)
{ {
for (unsigned int i = 0; i < rank; i++) for (size_t i = 0; i < rank; i++)
Base::elems[i] = extents[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)
@ -935,20 +938,20 @@ public:
_CONSTEXPR size_type total_size() const _NOEXCEPT _CONSTEXPR size_type total_size() const _NOEXCEPT
{ {
size_type ret = 0; 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]; ret += (Base::elems[i] - 1) * m_strides[i];
return ret + 1; return ret + 1;
} }
_CONSTEXPR size_type size() const _NOEXCEPT _CONSTEXPR size_type size() const _NOEXCEPT
{ {
size_type ret = 1; size_type ret = 1;
for (unsigned int i = 0; i < rank; ++i) for (size_t i = 0; i < rank; ++i)
ret *= Base::elems[i]; ret *= Base::elems[i];
return ret; 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]) if (idx[i] < 0 || idx[i] >= Base::elems[i])
return false; return false;
@ -958,7 +961,7 @@ public:
_CONSTEXPR size_type linearize(const index_type & idx) const _CONSTEXPR size_type linearize(const index_type & idx) const
{ {
size_type ret = 0; 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"); fail_fast_assert(idx[i] < Base::elems[i], "index is out of bounds of the array");
ret += idx[i] * m_strides[i]; ret += idx[i] * m_strides[i];
@ -974,7 +977,7 @@ public:
{ {
return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) };
} }
template <unsigned int Dim = 0> template <size_t Dim = 0>
_CONSTEXPR size_type extent() const _NOEXCEPT _CONSTEXPR size_type extent() const _NOEXCEPT
{ {
static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)");
@ -1000,7 +1003,7 @@ template <typename T>
struct is_bounds : std::integral_constant<bool, false> {}; struct is_bounds : std::integral_constant<bool, false> {};
template <typename SizeType, size_t... Ranges> template <typename SizeType, size_t... Ranges>
struct is_bounds<static_bounds<SizeType, Ranges...>> : std::integral_constant<bool, true> {}; struct is_bounds<static_bounds<SizeType, Ranges...>> : std::integral_constant<bool, true> {};
template <unsigned int Rank, typename SizeType> template <size_t Rank, typename SizeType>
struct is_bounds<strided_bounds<Rank, SizeType>> : std::integral_constant<bool, true> {}; struct is_bounds<strided_bounds<Rank, SizeType>> : std::integral_constant<bool, true> {};
template <typename IndexType> template <typename IndexType>
@ -1014,7 +1017,7 @@ class bounds_iterator
private: private:
using Base = std::iterator <std::random_access_iterator_tag, IndexType, ptrdiff_t, const details::arrow_proxy<IndexType>, const IndexType>; using Base = std::iterator <std::random_access_iterator_tag, IndexType, ptrdiff_t, const details::arrow_proxy<IndexType>, const IndexType>;
public: public:
static const unsigned int rank = IndexType::rank; static const size_t rank = IndexType::rank;
using typename Base::reference; using typename Base::reference;
using typename Base::pointer; using typename Base::pointer;
using typename Base::difference_type; using typename Base::difference_type;
@ -1038,7 +1041,7 @@ public:
} }
bounds_iterator& operator++() _NOEXCEPT bounds_iterator& operator++() _NOEXCEPT
{ {
for (unsigned int i = rank; i-- > 0;) for (size_t i = rank; i-- > 0;)
{ {
if (++curr[i] < boundary[i]) if (++curr[i] < boundary[i])
{ {
@ -1050,7 +1053,7 @@ public:
} }
} }
// If we're here we've wrapped over - set to past-the-end. // 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]; curr[i] = boundary[i];
} }
@ -1096,11 +1099,11 @@ public:
auto linear_idx = linearize(curr) + n; auto linear_idx = linearize(curr) + n;
value_type stride; value_type stride;
stride[rank - 1] = 1; 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]; 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]; curr[i] = linear_idx / stride[i];
linear_idx = linear_idx % stride[i]; linear_idx = linear_idx % stride[i];
@ -1134,7 +1137,7 @@ public:
} }
bool operator<(const bounds_iterator& rhs) const _NOEXCEPT 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]) if (curr[i] < rhs.curr[i])
return true; return true;
@ -1164,7 +1167,7 @@ private:
// TODO: Smarter impl. // TODO: Smarter impl.
// Check if past-the-end // Check if past-the-end
bool pte = true; bool pte = true;
for (unsigned int i = 0; i < rank; ++i) for (size_t i = 0; i < rank; ++i)
{ {
if (idx[i] != boundary[i]) if (idx[i] != boundary[i])
{ {
@ -1177,7 +1180,7 @@ private:
if (pte) if (pte)
{ {
res = 1; res = 1;
for (unsigned int i = rank; i-- > 0;) for (size_t i = rank; i-- > 0;)
{ {
res += (idx[i] - 1) * multiplier; res += (idx[i] - 1) * multiplier;
multiplier *= boundary[i]; multiplier *= boundary[i];
@ -1185,7 +1188,7 @@ private:
} }
else else
{ {
for (unsigned int i = rank; i-- > 0;) for (size_t i = rank; i-- > 0;)
{ {
res += idx[i] * multiplier; res += idx[i] * multiplier;
multiplier *= boundary[i]; multiplier *= boundary[i];
@ -1359,7 +1362,7 @@ template <typename ValueType, typename BoundsType>
class basic_array_view class basic_array_view
{ {
public: public:
static const unsigned int rank = BoundsType::rank; static const size_t rank = BoundsType::rank;
using bounds_type = BoundsType; using bounds_type = BoundsType;
using size_type = typename bounds_type::size_type; using size_type = typename bounds_type::size_type;
using index_type = typename bounds_type::index_type; using index_type = typename bounds_type::index_type;
@ -1381,7 +1384,7 @@ public:
{ {
return m_bounds; return m_bounds;
} }
template <unsigned int Dim = 0> template <size_t Dim = 0>
_CONSTEXPR size_type extent() const _NOEXCEPT _CONSTEXPR size_type extent() const _NOEXCEPT
{ {
static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)");
@ -1537,7 +1540,7 @@ struct dim<dynamic_range>
template <typename ValueTypeOpt, size_t FirstDimension = dynamic_range, size_t... RestDimensions> template <typename ValueTypeOpt, size_t FirstDimension = dynamic_range, size_t... RestDimensions>
class array_view; class array_view;
template <typename ValueTypeOpt, unsigned int Rank> template <typename ValueTypeOpt, size_t Rank>
class strided_array_view; class strided_array_view;
namespace details namespace details
@ -1616,7 +1619,7 @@ namespace details
template <typename ValueType, size_t FirstDimension, size_t... RestDimensions> template <typename ValueType, size_t FirstDimension, size_t... RestDimensions>
struct is_array_view_oracle<array_view<ValueType, FirstDimension, RestDimensions...>> : std::true_type struct is_array_view_oracle<array_view<ValueType, FirstDimension, RestDimensions...>> : std::true_type
{}; {};
template <typename ValueType, unsigned int Rank> template <typename ValueType, size_t Rank>
struct is_array_view_oracle<strided_array_view<ValueType, Rank>> : std::true_type struct is_array_view_oracle<strided_array_view<ValueType, Rank>> : std::true_type
{}; {};
template <typename T> template <typename T>
@ -1930,12 +1933,12 @@ template <typename Cont>
_CONSTEXPR auto as_array_view(Cont &&arr) -> std::enable_if_t<!details::is_array_view<std::decay_t<Cont>>::value, _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; array_view<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete;
template <typename ValueTypeOpt, unsigned int Rank> 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>> class strided_array_view : public basic_array_view<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type>>
{ {
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<typename details::ArrayViewTypeTraits<ValueTypeOpt>::value_type, strided_bounds<Rank, typename details::ArrayViewTypeTraits<ValueTypeOpt>::size_type>>;
template<typename OtherValueOpt, unsigned int OtherRank> template<typename OtherValueOpt, size_t OtherRank>
friend class strided_array_view; friend class strided_array_view;
public: public:
using Base::rank; using Base::rank;
@ -2286,3 +2289,5 @@ general_array_view_iterator<ArrayView> operator+(typename general_array_view_ite
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#pragma pop_macro("_NOEXCEPT") #pragma pop_macro("_NOEXCEPT")
#endif // GSL_ARRAY_VIEW_H

View File

@ -16,6 +16,9 @@
#pragma once #pragma once
#ifndef GSL_FAIL_FAST_H
#define GSL_FAIL_FAST_H
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
@ -45,3 +48,5 @@ inline void fail_fast_assert(bool cond, const char* const) { if (!cond) std::ter
#endif // SAFER_CPP_TESTING #endif // SAFER_CPP_TESTING
} }
#endif // GSL_FAIL_FAST_H

View File

@ -16,6 +16,9 @@
#pragma once #pragma once
#ifndef GSL_GSL_H
#define GSL_GSL_H
#include "array_view.h" // array_view, strided_array_view... #include "array_view.h" // array_view, strided_array_view...
#include "string_view.h" // zstring, string_view, zstring_builder... #include "string_view.h" // zstring, string_view, zstring_builder...
#include <memory> #include <memory>
@ -47,7 +50,7 @@ template <class F>
class Final_act class Final_act
{ {
public: 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&& other) : f_(other.f_) {}
Final_act(const Final_act&) = delete; Final_act(const Final_act&) = delete;
@ -61,7 +64,10 @@ private:
// finally() - convenience function to generate a Final_act // finally() - convenience function to generate a Final_act
template <class F> template <class F>
Final_act<F> finally(F f) { return Final_act<F>(f); } Final_act<F> finally(const F &f) { return Final_act<F>(f); }
template <class F>
Final_act<F> finally(F &&f) { return Final_act<F>(std::forward<F>(f)); }
// narrow_cast(): a searchable way to do narrowing casts of values // narrow_cast(): a searchable way to do narrowing casts of values
template<class T, class U> template<class T, class U>
@ -102,6 +108,7 @@ typename Cont::value_type& at(Cont& cont, size_t index) { fail_fast_assert(index
template<class T> template<class T>
class not_null class not_null
{ {
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public: public:
not_null(T t) : ptr_(t) { ensure_invariant(); } not_null(T t) : ptr_(t) { ensure_invariant(); }
@ -162,6 +169,7 @@ private:
template<class T> template<class T>
class maybe_null_dbg class maybe_null_dbg
{ {
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public: public:
maybe_null_dbg() : ptr_(nullptr), tested_(false) {} maybe_null_dbg() : ptr_(nullptr), tested_(false) {}
@ -237,6 +245,7 @@ private:
template<class T> template<class T>
class maybe_null_ret class maybe_null_ret
{ {
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public: public:
maybe_null_ret() : ptr_(nullptr) {} maybe_null_ret() : ptr_(nullptr) {}
maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {}
@ -287,3 +296,5 @@ private:
template<class T> using maybe_null = maybe_null_ret<T>; template<class T> using maybe_null = maybe_null_ret<T>;
} // namespace Guide } // namespace Guide
#endif // GSL_GSL_H

View File

@ -16,6 +16,9 @@
#pragma once #pragma once
#ifndef GSL_STRING_VIEW_H
#define GSL_STRING_VIEW_H
#include "array_view.h" #include "array_view.h"
#include <cstring> #include <cstring>
@ -176,3 +179,5 @@ using zstring_builder = basic_zstring_builder<char, Max>;
template <size_t Max = dynamic_range> template <size_t Max = dynamic_range>
using wzstring_builder = basic_zstring_builder<wchar_t, Max>; using wzstring_builder = basic_zstring_builder<wchar_t, Max>;
} }
#endif // GSL_STRING_VIEW_H

View File

@ -16,6 +16,7 @@
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl.h> #include <gsl.h>
#include <vector>
using namespace Guide; using namespace Guide;
@ -27,12 +28,24 @@ SUITE(MaybeNullTests)
{ {
TEST(TestMaybeNull1) TEST(TestMaybeNull1)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS
// Forbid non-nullptr assignable types
maybe_null_ret<std::vector<int>> f_ret(std::vector<int>{1});
maybe_null_ret<std::vector<int>> f_ret(std::vector<int>{1});
maybe_null_ret<int> z_ret(10);
maybe_null_dbg<std::vector<int>> y_dbg({1,2});
maybe_null_dbg<int> z_dbg(10);
maybe_null_dbg<std::vector<int>> y_dbg({1,2});
#endif
int n = 5; int n = 5;
maybe_null_dbg<int *> opt_n(&n); maybe_null_dbg<int *> opt_n(&n);
int result = 0; int result = 0;
bool threw = false; bool threw = false;
CHECK_THROW(result = *opt_n, fail_fast); CHECK_THROW(result = *opt_n, fail_fast);
maybe_null_ret<std::shared_ptr<int>> x_ret(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
maybe_null_dbg<std::shared_ptr<int>> x_dbg(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
} }
TEST(TestMaybeNull2) TEST(TestMaybeNull2)

View File

@ -16,6 +16,7 @@
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl.h> #include <gsl.h>
#include <vector>
using namespace Guide; using namespace Guide;
@ -48,11 +49,18 @@ SUITE(NotNullTests)
not_null<int*> p; // yay...does not compile! not_null<int*> p; // yay...does not compile!
std::unique_ptr<int> up = std::make_unique<int>(120); std::unique_ptr<int> up = std::make_unique<int>(120);
not_null<int*> p = up; not_null<int*> p = up;
// Forbid non-nullptr assignable types
not_null<std::vector<int>> f(std::vector<int>{1});
not_null<int> z(10);
not_null<std::vector<int>> y({1,2});
#endif #endif
int i = 12; int i = 12;
auto rp = RefCounted<int>(&i); auto rp = RefCounted<int>(&i);
not_null<int*> p(rp); not_null<int*> p(rp);
CHECK(p.get() == &i); CHECK(p.get() == &i);
not_null<std::shared_ptr<int>> x(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
} }
TEST(TestNotNullCasting) TEST(TestNotNullCasting)