add gsl::index typedef (#620)

* rename index in multi_span to span_index

gsl::index is name reserved for different type

* add gsl::index typedef

cppcoreguidelines referece: ES.107: Don't use unsigned for subscripts, prefer gsl::index

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Res-subscripts

* rename span_index to multi_span_index
This commit is contained in:
paweldac 2018-02-21 22:33:07 +01:00 committed by Neil MacIntosh
parent 73db6ef98f
commit b3870ca020
6 changed files with 137 additions and 127 deletions

View File

@ -43,6 +43,9 @@ namespace gsl
// GSL.util: utilities // GSL.util: utilities
// //
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;
// final_action allows you to ensure something gets run at the end of a scope // final_action allows you to ensure something gets run at the end of a scope
template <class F> template <class F>
class final_action class final_action
@ -117,25 +120,25 @@ T narrow(U u)
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
// //
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr T& at(T (&arr)[N], const std::ptrdiff_t index) constexpr T& at(T (&arr)[N], const index i)
{ {
Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(N)); Expects(i >= 0 && i < narrow_cast<index>(N));
return arr[static_cast<std::size_t>(index)]; return arr[static_cast<std::size_t>(i)];
} }
template <class Cont> template <class Cont>
constexpr auto at(Cont& cont, const std::ptrdiff_t index) -> decltype(cont[cont.size()]) constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{ {
Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size())); Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
using size_type = decltype(cont.size()); using size_type = decltype(cont.size());
return cont[static_cast<size_type>(index)]; return cont[static_cast<size_type>(i)];
} }
template <class T> template <class T>
constexpr T at(const std::initializer_list<T> cont, const std::ptrdiff_t index) constexpr T at(const std::initializer_list<T> cont, const index i)
{ {
Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size())); Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
return *(cont.begin() + index); return *(cont.begin() + i);
} }
} // namespace gsl } // namespace gsl

View File

@ -85,12 +85,12 @@ namespace details
} }
template <std::size_t Rank> template <std::size_t Rank>
class index final class multi_span_index final
{ {
static_assert(Rank > 0, "Rank must be greater than 0!"); static_assert(Rank > 0, "Rank must be greater than 0!");
template <std::size_t OtherRank> template <std::size_t OtherRank>
friend class index; friend class multi_span_index;
public: public:
static const std::size_t rank = Rank; static const std::size_t rank = Rank;
@ -99,22 +99,22 @@ public:
using reference = std::add_lvalue_reference_t<value_type>; using reference = std::add_lvalue_reference_t<value_type>;
using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>; using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;
constexpr index() GSL_NOEXCEPT {} constexpr multi_span_index() GSL_NOEXCEPT {}
constexpr index(const value_type (&values)[Rank]) GSL_NOEXCEPT constexpr multi_span_index(const value_type (&values)[Rank]) GSL_NOEXCEPT
{ {
std::copy(values, values + Rank, elems); std::copy(values, values + Rank, elems);
} }
template <typename... Ts, typename = std::enable_if_t<(sizeof...(Ts) == Rank) && template <typename... Ts, typename = std::enable_if_t<(sizeof...(Ts) == Rank) &&
details::are_integral<Ts...>::value>> details::are_integral<Ts...>::value>>
constexpr index(Ts... ds) GSL_NOEXCEPT : elems{narrow_cast<value_type>(ds)...} constexpr multi_span_index(Ts... ds) GSL_NOEXCEPT : elems{narrow_cast<value_type>(ds)...}
{ {
} }
constexpr index(const index& other) GSL_NOEXCEPT = default; constexpr multi_span_index(const multi_span_index& other) GSL_NOEXCEPT = default;
constexpr index& operator=(const index& rhs) GSL_NOEXCEPT = default; constexpr multi_span_index& operator=(const multi_span_index& rhs) GSL_NOEXCEPT = default;
// Preconditions: component_idx < rank // Preconditions: component_idx < rank
constexpr reference operator[](std::size_t component_idx) constexpr reference operator[](std::size_t component_idx)
@ -130,75 +130,75 @@ public:
return elems[component_idx]; return elems[component_idx];
} }
constexpr bool operator==(const index& rhs) const GSL_NOEXCEPT constexpr bool operator==(const multi_span_index& rhs) const GSL_NOEXCEPT
{ {
return std::equal(elems, elems + rank, rhs.elems); return std::equal(elems, elems + rank, rhs.elems);
} }
constexpr bool operator!=(const index& rhs) const GSL_NOEXCEPT { return !(*this == rhs); } constexpr bool operator!=(const multi_span_index& rhs) const GSL_NOEXCEPT { return !(*this == rhs); }
constexpr index operator+() const GSL_NOEXCEPT { return *this; } constexpr multi_span_index operator+() const GSL_NOEXCEPT { return *this; }
constexpr index operator-() const GSL_NOEXCEPT constexpr multi_span_index operator-() const GSL_NOEXCEPT
{ {
index ret = *this; multi_span_index ret = *this;
std::transform(ret, ret + rank, ret, std::negate<value_type>{}); std::transform(ret, ret + rank, ret, std::negate<value_type>{});
return ret; return ret;
} }
constexpr index operator+(const index& rhs) const GSL_NOEXCEPT constexpr multi_span_index operator+(const multi_span_index& rhs) const GSL_NOEXCEPT
{ {
index ret = *this; multi_span_index ret = *this;
ret += rhs; ret += rhs;
return ret; return ret;
} }
constexpr index operator-(const index& rhs) const GSL_NOEXCEPT constexpr multi_span_index operator-(const multi_span_index& rhs) const GSL_NOEXCEPT
{ {
index ret = *this; multi_span_index ret = *this;
ret -= rhs; ret -= rhs;
return ret; return ret;
} }
constexpr index& operator+=(const index& rhs) GSL_NOEXCEPT constexpr multi_span_index& operator+=(const multi_span_index& rhs) GSL_NOEXCEPT
{ {
std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{}); std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{});
return *this; return *this;
} }
constexpr index& operator-=(const index& rhs) GSL_NOEXCEPT constexpr multi_span_index& operator-=(const multi_span_index& rhs) GSL_NOEXCEPT
{ {
std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{}); std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{});
return *this; return *this;
} }
constexpr index operator*(value_type v) const GSL_NOEXCEPT constexpr multi_span_index operator*(value_type v) const GSL_NOEXCEPT
{ {
index ret = *this; multi_span_index ret = *this;
ret *= v; ret *= v;
return ret; return ret;
} }
constexpr index operator/(value_type v) const GSL_NOEXCEPT constexpr multi_span_index operator/(value_type v) const GSL_NOEXCEPT
{ {
index ret = *this; multi_span_index ret = *this;
ret /= v; ret /= v;
return ret; return ret;
} }
friend constexpr index operator*(value_type v, const index& rhs) GSL_NOEXCEPT friend constexpr multi_span_index operator*(value_type v, const multi_span_index& rhs) GSL_NOEXCEPT
{ {
return rhs * v; return rhs * v;
} }
constexpr index& operator*=(value_type v) GSL_NOEXCEPT constexpr multi_span_index& operator*=(value_type v) GSL_NOEXCEPT
{ {
std::transform(elems, elems + rank, elems, std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::multiplies<value_type>{}(x, v); }); [v](value_type x) { return std::multiplies<value_type>{}(x, v); });
return *this; return *this;
} }
constexpr index& operator/=(value_type v) GSL_NOEXCEPT constexpr multi_span_index& operator/=(value_type v) GSL_NOEXCEPT
{ {
std::transform(elems, elems + rank, elems, std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::divides<value_type>{}(x, v); }); [v](value_type x) { return std::divides<value_type>{}(x, v); });
@ -497,8 +497,8 @@ namespace details
} }
template <std::size_t Rank, bool Enabled = (Rank > 1), template <std::size_t Rank, bool Enabled = (Rank > 1),
typename Ret = std::enable_if_t<Enabled, index<Rank - 1>>> typename Ret = std::enable_if_t<Enabled, multi_span_index<Rank - 1>>>
constexpr Ret shift_left(const index<Rank>& other) GSL_NOEXCEPT constexpr Ret shift_left(const multi_span_index<Rank>& other) GSL_NOEXCEPT
{ {
Ret ret{}; Ret ret{};
for (std::size_t i = 0; i < Rank - 1; ++i) { for (std::size_t i = 0; i < Rank - 1; ++i) {
@ -535,7 +535,7 @@ public:
static const std::ptrdiff_t static_size = MyRanges::TotalSize; static const std::ptrdiff_t static_size = MyRanges::TotalSize;
using size_type = std::ptrdiff_t; using size_type = std::ptrdiff_t;
using index_type = index<rank>; using index_type = multi_span_index<rank>;
using const_index_type = std::add_const_t<index_type>; using const_index_type = std::add_const_t<index_type>;
using iterator = bounds_iterator<const_index_type>; using iterator = bounds_iterator<const_index_type>;
using const_iterator = bounds_iterator<const_index_type>; using const_iterator = bounds_iterator<const_index_type>;
@ -631,9 +631,9 @@ public:
return m_ranges.contains(idx) != -1; return m_ranges.contains(idx) != -1;
} }
constexpr size_type operator[](std::size_t index) const GSL_NOEXCEPT constexpr size_type operator[](std::size_t idx) const GSL_NOEXCEPT
{ {
return m_ranges.elementNum(index); return m_ranges.elementNum(idx);
} }
template <std::size_t Dim = 0> template <std::size_t Dim = 0>
@ -698,7 +698,7 @@ public:
using const_reference = std::add_const_t<reference>; using const_reference = std::add_const_t<reference>;
using size_type = value_type; using size_type = value_type;
using difference_type = value_type; using difference_type = value_type;
using index_type = index<rank>; using index_type = multi_span_index<rank>;
using const_index_type = std::add_const_t<index_type>; using const_index_type = std::add_const_t<index_type>;
using iterator = bounds_iterator<const_index_type>; using iterator = bounds_iterator<const_index_type>;
using const_iterator = bounds_iterator<const_index_type>; using const_iterator = bounds_iterator<const_index_type>;
@ -1478,15 +1478,15 @@ public:
constexpr pointer data() const GSL_NOEXCEPT { return data_; } constexpr pointer data() const GSL_NOEXCEPT { return data_; }
template <typename FirstIndex> template <typename FirstIndex>
constexpr reference operator()(FirstIndex index) constexpr reference operator()(FirstIndex idx)
{ {
return this->operator[](narrow_cast<std::ptrdiff_t>(index)); return this->operator[](narrow_cast<std::ptrdiff_t>(idx));
} }
template <typename FirstIndex, typename... OtherIndices> template <typename FirstIndex, typename... OtherIndices>
constexpr reference operator()(FirstIndex index, OtherIndices... indices) constexpr reference operator()(FirstIndex firstIndex, OtherIndices... indices)
{ {
index_type idx = {narrow_cast<std::ptrdiff_t>(index), index_type idx = {narrow_cast<std::ptrdiff_t>(firstIndex),
narrow_cast<std::ptrdiff_t>(indices)...}; narrow_cast<std::ptrdiff_t>(indices)...};
return this->operator[](idx); return this->operator[](idx);
} }

View File

@ -125,10 +125,10 @@ namespace details
span_iterator() = default; span_iterator() = default;
constexpr span_iterator(const Span* span, typename Span::index_type index) GSL_NOEXCEPT constexpr span_iterator(const Span* span, typename Span::index_type idx) GSL_NOEXCEPT
: span_(span), index_(index) : span_(span), index_(idx)
{ {
Expects(span == nullptr || (0 <= index_ && index <= span_->size())); Expects(span == nullptr || (0 <= index_ && index_ <= span_->size()));
} }
friend span_iterator<Span, true>; friend span_iterator<Span, true>;
@ -662,10 +662,10 @@ span<typename Ptr::element_type> make_span(Ptr& cont)
// Specialization of gsl::at for span // Specialization of gsl::at for span
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr ElementType& at(span<ElementType, Extent> s, std::ptrdiff_t index) constexpr ElementType& at(span<ElementType, Extent> s, index i)
{ {
// No bounds checking here because it is done in span::operator[] called below // No bounds checking here because it is done in span::operator[] called below
return s[index]; return s[i];
} }
} // namespace gsl } // namespace gsl

View File

@ -1243,7 +1243,7 @@ TEST_CASE("empty_spans")
{ {
multi_span<int, 0> empty_av(nullptr); multi_span<int, 0> empty_av(nullptr);
CHECK(empty_av.bounds().index_bounds() == index<1>{0}); CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_av[0], fail_fast); CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
@ -1255,7 +1255,7 @@ TEST_CASE("empty_spans")
{ {
multi_span<int> empty_av = {}; multi_span<int> empty_av = {};
CHECK(empty_av.bounds().index_bounds() == index<1>{0}); CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_av[0], fail_fast); CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
@ -1277,13 +1277,13 @@ TEST_CASE("index_constructor")
multi_span<int, dynamic_range> av(arr, 8); multi_span<int, dynamic_range> av(arr, 8);
ptrdiff_t a[1] = {0}; ptrdiff_t a[1] = {0};
index<1> i = a; multi_span_index<1> i = a;
CHECK(av[i] == 4); CHECK(av[i] == 4);
auto av2 = as_multi_span(av, dim<4>(), dim(2)); auto av2 = as_multi_span(av, dim<4>(), dim(2));
ptrdiff_t a2[2] = {0, 1}; ptrdiff_t a2[2] = {0, 1};
index<2> i2 = a2; multi_span_index<2> i2 = a2;
CHECK(av2[i2] == 0); CHECK(av2[i2] == 0);
CHECK(av2[0][i] == 4); CHECK(av2[0][i] == 4);
@ -1295,70 +1295,70 @@ TEST_CASE("index_constructors")
{ {
{ {
// components of the same type // components of the same type
index<3> i1(0, 1, 2); multi_span_index<3> i1(0, 1, 2);
CHECK(i1[0] == 0); CHECK(i1[0] == 0);
// components of different types // components of different types
std::size_t c0 = 0; std::size_t c0 = 0;
std::size_t c1 = 1; std::size_t c1 = 1;
index<3> i2(c0, c1, 2); multi_span_index<3> i2(c0, c1, 2);
CHECK(i2[0] == 0); CHECK(i2[0] == 0);
// from array // from array
index<3> i3 = {0, 1, 2}; multi_span_index<3> i3 = {0, 1, 2};
CHECK(i3[0] == 0); CHECK(i3[0] == 0);
// from other index of the same size type // from other index of the same size type
index<3> i4 = i3; multi_span_index<3> i4 = i3;
CHECK(i4[0] == 0); CHECK(i4[0] == 0);
// default // default
index<3> i7; multi_span_index<3> i7;
CHECK(i7[0] == 0); CHECK(i7[0] == 0);
// default // default
index<3> i9 = {}; multi_span_index<3> i9 = {};
CHECK(i9[0] == 0); CHECK(i9[0] == 0);
} }
{ {
// components of the same type // components of the same type
index<1> i1(0); multi_span_index<1> i1(0);
CHECK(i1[0] == 0); CHECK(i1[0] == 0);
// components of different types // components of different types
std::size_t c0 = 0; std::size_t c0 = 0;
index<1> i2(c0); multi_span_index<1> i2(c0);
CHECK(i2[0] == 0); CHECK(i2[0] == 0);
// from array // from array
index<1> i3 = {0}; multi_span_index<1> i3 = {0};
CHECK(i3[0] == 0); CHECK(i3[0] == 0);
// from int // from int
index<1> i4 = 0; multi_span_index<1> i4 = 0;
CHECK(i4[0] == 0); CHECK(i4[0] == 0);
// from other index of the same size type // from other index of the same size type
index<1> i5 = i3; multi_span_index<1> i5 = i3;
CHECK(i5[0] == 0); CHECK(i5[0] == 0);
// default // default
index<1> i8; multi_span_index<1> i8;
CHECK(i8[0] == 0); CHECK(i8[0] == 0);
// default // default
index<1> i9 = {}; multi_span_index<1> i9 = {};
CHECK(i9[0] == 0); CHECK(i9[0] == 0);
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
index<3> i1(0, 1); multi_span_index<3> i1(0, 1);
index<3> i2(0, 1, 2, 3); multi_span_index<3> i2(0, 1, 2, 3);
index<3> i3 = {0}; multi_span_index<3> i3 = {0};
index<3> i4 = {0, 1, 2, 3}; multi_span_index<3> i4 = {0, 1, 2, 3};
index<1> i5 = {0, 1}; multi_span_index<1> i5 = {0, 1};
} }
#endif #endif
} }
@ -1367,15 +1367,15 @@ TEST_CASE("index_operations")
{ {
ptrdiff_t a[3] = {0, 1, 2}; ptrdiff_t a[3] = {0, 1, 2};
ptrdiff_t b[3] = {3, 4, 5}; ptrdiff_t b[3] = {3, 4, 5};
index<3> i = a; multi_span_index<3> i = a;
index<3> j = b; multi_span_index<3> j = b;
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
CHECK(i[2] == 2); CHECK(i[2] == 2);
{ {
index<3> k = i + j; multi_span_index<3> k = i + j;
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
@ -1386,7 +1386,7 @@ TEST_CASE("index_operations")
} }
{ {
index<3> k = i * 3; multi_span_index<3> k = i * 3;
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
@ -1397,7 +1397,7 @@ TEST_CASE("index_operations")
} }
{ {
index<3> k = 3 * i; multi_span_index<3> k = 3 * i;
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
@ -1408,7 +1408,7 @@ TEST_CASE("index_operations")
} }
{ {
index<2> k = details::shift_left(i); multi_span_index<2> k = details::shift_left(i);
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
@ -1431,7 +1431,7 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
} }
for (auto i = 0; i < section.size(); ++i) { for (auto i = 0; i < section.size(); ++i) {
auto idx = index<2>{i, 0}; // avoid braces inside the CHECK macro auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]); CHECK(section[idx] == av[i][1]);
} }
@ -1439,7 +1439,7 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
CHECK(section.bounds().index_bounds()[1] == 1); CHECK(section.bounds().index_bounds()[1] == 1);
for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) { for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) {
for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) { for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) {
auto idx = index<2>{i, j}; // avoid braces inside the CHECK macro auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]); CHECK(section[idx] == av[i][1]);
} }
} }

View File

@ -48,8 +48,8 @@ TEST_CASE("span_section_test")
int a[30][4][5]; int a[30][4][5];
const auto av = as_multi_span(a); const auto av = as_multi_span(a);
const auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2}); const auto sub = av.section({15, 0, 0}, gsl::multi_span_index<3>{2, 2, 2});
const auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1}); const auto subsub = sub.section({1, 0, 0}, gsl::multi_span_index<3>{1, 1, 1});
(void) subsub; (void) subsub;
} }
@ -79,18 +79,18 @@ TEST_CASE("strided_span_constructors")
const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
CHECK(sav1.bounds().index_bounds() == index<1>{9}); CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{9});
CHECK(sav1.bounds().stride() == 1); CHECK(sav1.bounds().stride() == 1);
CHECK((sav1[0] == 1 && sav1[8] == 9)); CHECK((sav1[0] == 1 && sav1[8] == 9));
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
CHECK(sav2.bounds().index_bounds() == index<1>{4}); CHECK(sav2.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav2.bounds().strides() == index<1>{2}); CHECK(sav2.bounds().strides() == multi_span_index<1>{2});
CHECK((sav2[0] == 1 && sav2[3] == 7)); CHECK((sav2[0] == 1 && sav2[3] == 7));
strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
CHECK((sav3.bounds().index_bounds() == index<2>{2, 2})); CHECK((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
CHECK((sav3.bounds().strides() == index<2>{6, 2})); CHECK((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7)); CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7));
} }
@ -103,8 +103,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<int> src = arr; const multi_span<int> src = arr;
strided_span<int, 1> sav{src, {2, 1}}; strided_span<int, 1> sav{src, {2, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{2}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().strides() == index<1>{1}); CHECK(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[1] == 2); CHECK(sav[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
@ -115,8 +115,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const int, 1> sav_c{multi_span<const int>{src}, strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_c.bounds().index_bounds() == index<1>{2}); CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_c.bounds().strides() == index<1>{1}); CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
@ -125,8 +125,8 @@ TEST_CASE("strided_span_constructors")
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src}, strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_v.bounds().index_bounds() == index<1>{2}); CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_v.bounds().strides() == index<1>{1}); CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
@ -135,8 +135,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{2}); CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{1}); CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
@ -145,8 +145,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<const int> src{arr}; const multi_span<const int> src{arr};
strided_span<const int, 1> sav_c{src, {2, 1}}; strided_span<const int, 1> sav_c{src, {2, 1}};
CHECK(sav_c.bounds().index_bounds() == index<1>{2}); CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_c.bounds().strides() == index<1>{1}); CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
@ -156,8 +156,8 @@ TEST_CASE("strided_span_constructors")
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{2}); CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{1}); CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
@ -166,8 +166,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<volatile int> src{arr}; const multi_span<volatile int> src{arr};
strided_span<volatile int, 1> sav_v{src, {2, 1}}; strided_span<volatile int, 1> sav_v{src, {2, 1}};
CHECK(sav_v.bounds().index_bounds() == index<1>{2}); CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_v.bounds().strides() == index<1>{1}); CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
@ -176,8 +176,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{2}); CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{1}); CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
@ -186,8 +186,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<const volatile int> src{arr}; const multi_span<const volatile int> src{arr};
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
CHECK(sav_cv.bounds().index_bounds() == index<1>{2}); CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{1}); CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
} }
@ -206,7 +206,7 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr, {2, 1}}; const strided_span<int, 1> src{arr, {2, 1}};
strided_span<const int, 1> sav{src}; strided_span<const int, 1> sav{src};
CHECK(sav.bounds().index_bounds() == index<1>{2}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().stride() == 1); CHECK(sav.bounds().stride() == 1);
CHECK(sav[1] == 5); CHECK(sav[1] == 5);
@ -221,15 +221,15 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src1{arr1, {2, 1}}; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{src1}; strided_span<int, 1> sav1{src1};
CHECK(sav1.bounds().index_bounds() == index<1>{2}); CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav1.bounds().stride() == 1); CHECK(sav1.bounds().stride() == 1);
CHECK(sav1[0] == 3); CHECK(sav1[0] == 3);
int arr2[6] = {1, 2, 3, 4, 5, 6}; int arr2[6] = {1, 2, 3, 4, 5, 6};
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}}; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{src2}; strided_span<const int, 2> sav2{src2};
CHECK((sav2.bounds().index_bounds() == index<2>{3, 2})); CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((sav2.bounds().strides() == index<2>{2, 1})); CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
} }
@ -241,8 +241,8 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr1, {{2}, {1}}}; const strided_span<int, 1> src{arr1, {{2}, {1}}};
strided_span<const int, 1> sav{arr2, {{3}, {2}}}; strided_span<const int, 1> sav{arr2, {{3}, {2}}};
strided_span<const int, 1>& sav_ref = (sav = src); strided_span<const int, 1>& sav_ref = (sav = src);
CHECK(sav.bounds().index_bounds() == index<1>{2}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().strides() == index<1>{1}); CHECK(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[0] == 1); CHECK(sav[0] == 1);
CHECK(&sav_ref == &sav); CHECK(&sav_ref == &sav);
} }
@ -254,8 +254,8 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src1{arr1, {2, 1}}; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{arr1b, {1, 1}}; strided_span<int, 1> sav1{arr1b, {1, 1}};
strided_span<int, 1>& sav1_ref = (sav1 = src1); strided_span<int, 1>& sav1_ref = (sav1 = src1);
CHECK(sav1.bounds().index_bounds() == index<1>{2}); CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav1.bounds().strides() == index<1>{1}); CHECK(sav1.bounds().strides() == multi_span_index<1>{1});
CHECK(sav1[0] == 3); CHECK(sav1[0] == 3);
CHECK(&sav1_ref == &sav1); CHECK(&sav1_ref == &sav1);
@ -264,8 +264,8 @@ TEST_CASE("strided_span_constructors")
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}}; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}}; strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}};
strided_span<const int, 2>& sav2_ref = (sav2 = src2); strided_span<const int, 2>& sav2_ref = (sav2 = src2);
CHECK((sav2.bounds().index_bounds() == index<2>{3, 2})); CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((sav2.bounds().strides() == index<2>{2, 1})); CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
CHECK(&sav2_ref == &sav2); CHECK(&sav2_ref == &sav2);
} }
@ -322,7 +322,7 @@ TEST_CASE("strided_span_column_major")
// Section // Section
strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2}); strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2});
CHECK((cm_sec.bounds().index_bounds() == index<2>{3, 2})); CHECK((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((cm_sec[{0, 0}] == 8)); CHECK((cm_sec[{0, 0}] == 8));
CHECK((cm_sec[{0, 1}] == 9)); CHECK((cm_sec[{0, 1}] == 9));
CHECK((cm_sec[{1, 0}] == 11)); CHECK((cm_sec[{1, 0}] == 11));
@ -371,7 +371,7 @@ TEST_CASE("strided_span_bounds")
{ {
// strided array ctor with matching strided bounds // strided array ctor with matching strided bounds
strided_span<int, 1> sav{arr, {4, 1}}; strided_span<int, 1> sav{arr, {4, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{4}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav[3] == 3); CHECK(sav[3] == 3);
CHECK_THROWS_AS(sav[4], fail_fast); CHECK_THROWS_AS(sav[4], fail_fast);
} }
@ -379,7 +379,7 @@ TEST_CASE("strided_span_bounds")
{ {
// strided array ctor with smaller strided bounds // strided array ctor with smaller strided bounds
strided_span<int, 1> sav{arr, {2, 1}}; strided_span<int, 1> sav{arr, {2, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{2}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[1] == 1); CHECK(sav[1] == 1);
CHECK_THROWS_AS(sav[2], fail_fast); CHECK_THROWS_AS(sav[2], fail_fast);
} }
@ -387,7 +387,7 @@ TEST_CASE("strided_span_bounds")
{ {
// strided array ctor with fitting irregular bounds // strided array ctor with fitting irregular bounds
strided_span<int, 1> sav{arr, {2, 3}}; strided_span<int, 1> sav{arr, {2, 3}};
CHECK(sav.bounds().index_bounds() == index<1>{2}); CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[0] == 0); CHECK(sav[0] == 0);
CHECK(sav[1] == 3); CHECK(sav[1] == 3);
CHECK_THROWS_AS(sav[2], fail_fast); CHECK_THROWS_AS(sav[2], fail_fast);
@ -433,7 +433,7 @@ TEST_CASE("strided_span_bounds")
strided_span<int, 2> sav7{av.as_multi_span(dim<2>(), dim<2>()), strided_span<int, 2> sav7{av.as_multi_span(dim<2>(), dim<2>()),
{{1, 1}, {1, 1}, {1, 1}}}; {{1, 1}, {1, 1}, {1, 1}}};
index<1> index{0, 1}; multi_span_index<1> index{0, 1};
strided_span<int, 1> sav8{arr, {1, {1, 1}}}; strided_span<int, 1> sav8{arr, {1, {1, 1}}};
strided_span<int, 1> sav9{arr, {{1, 1}, {1, 1}}}; strided_span<int, 1> sav9{arr, {{1, 1}, {1, 1}}};
strided_span<int, 1> sav10{av, {1, {1, 1}}}; strided_span<int, 1> sav10{av, {1, {1, 1}}};
@ -548,7 +548,7 @@ TEST_CASE("empty_strided_spans")
multi_span<int, 0> empty_av(nullptr); multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{empty_av, {0, 1}}; strided_span<int, 1> empty_sav{empty_av, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == index<1>{0}); CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_sav[0], fail_fast); CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
@ -562,7 +562,7 @@ TEST_CASE("empty_strided_spans")
{ {
strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}}; strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == index<1>{0}); CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_sav[0], fail_fast); CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
@ -582,7 +582,7 @@ void iterate_every_other_element(multi_span<int, dynamic_range> av)
#if _MSC_VER > 1800 #if _MSC_VER > 1800
auto bounds = strided_bounds<1>({length}, {2}); auto bounds = strided_bounds<1>({length}, {2});
#else #else
auto bounds = strided_bounds<1>(index<1>{length}, index<1>{2}); auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2});
#endif #endif
strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds); strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
@ -638,7 +638,7 @@ void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_
for (auto i = 0; i < section.extent<0>(); ++i) { for (auto i = 0; i < section.extent<0>(); ++i) {
for (auto j = 0; j < section.extent<1>(); ++j) for (auto j = 0; j < section.extent<1>(); ++j)
for (auto k = 0; k < section.extent<2>(); ++k) { for (auto k = 0; k < section.extent<2>(); ++k) {
auto idx = index<3>{i, j, k}; // avoid braces in the CHECK macro auto idx = multi_span_index<3>{i, j, k}; // avoid braces in the CHECK macro
CHECK(section[idx] == expected[2 * i + 2 * j + k]); CHECK(section[idx] == expected[2 * i + 2 * j + k]);
} }
} }

View File

@ -22,9 +22,16 @@
#include <functional> // for reference_wrapper, _Bind_helper<>::type #include <functional> // for reference_wrapper, _Bind_helper<>::type
#include <limits> // for numeric_limits #include <limits> // for numeric_limits
#include <stdint.h> // for uint32_t, int32_t #include <stdint.h> // for uint32_t, int32_t
#include <type_traits> // for is_same
using namespace gsl; using namespace gsl;
TEST_CASE("sanity check for gsl::index typedef")
{
static_assert(std::is_same<gsl::index, std::ptrdiff_t>::value,
"gsl::index represents wrong arithmetic type");
}
void f(int& i) { i += 1; } void f(int& i) { i += 1; }
TEST_CASE("finally_lambda") TEST_CASE("finally_lambda")