mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge pull request #1 from neilmacintosh/dev/annagrin/strided_array_view_bugfixes
Added support for all compiler and platform targets.
This commit is contained in:
commit
4328354581
@ -52,6 +52,11 @@
|
|||||||
|
|
||||||
#endif // _NOEXCEPT
|
#endif // _NOEXCEPT
|
||||||
|
|
||||||
|
#if _MSC_VER <= 1800
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior
|
||||||
|
#endif // _MSC_VER <= 1800
|
||||||
|
|
||||||
namespace Guide {
|
namespace Guide {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -290,7 +295,8 @@ public:
|
|||||||
}
|
}
|
||||||
_CONSTEXPR static index shift_left(const index<rank+1, value_type>& other) _NOEXCEPT
|
_CONSTEXPR static index shift_left(const index<rank+1, value_type>& other) _NOEXCEPT
|
||||||
{
|
{
|
||||||
return (value_type(&)[rank])other.elems[1];
|
value_type (&arr)[rank] = (value_type(&)[rank])(*(other.elems + 1));
|
||||||
|
return index(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Base::operator[];
|
using Base::operator[];
|
||||||
@ -1647,6 +1653,7 @@ public:
|
|||||||
using typename Base::index_type;
|
using typename Base::index_type;
|
||||||
using typename Base::iterator;
|
using typename Base::iterator;
|
||||||
using typename Base::const_iterator;
|
using typename Base::const_iterator;
|
||||||
|
using typename Base::reference;
|
||||||
using Base::rank;
|
using Base::rank;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1849,13 +1856,15 @@ public:
|
|||||||
// section
|
// section
|
||||||
_CONSTEXPR strided_array_view<ValueTypeOpt, rank> section(index_type origin, index_type extents) const
|
_CONSTEXPR strided_array_view<ValueTypeOpt, rank> section(index_type origin, index_type extents) const
|
||||||
{
|
{
|
||||||
size_type size = bounds().total_size() - bounds().linearize(origin);
|
size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
|
||||||
return { &this->operator[](origin), size, strided_bounds<rank, size_type> {extents, details::make_stride(Base::bounds())} };
|
return{ &this->operator[](origin), size, strided_bounds<rank, size_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);
|
return Base::operator[](idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Enabled = (rank > 1), typename Dummy = std::enable_if_t<Enabled>>
|
template <bool Enabled = (rank > 1), typename Dummy = std::enable_if_t<Enabled>>
|
||||||
_CONSTEXPR array_view<ValueTypeOpt, RestDimensions...> operator[](size_type idx) const
|
_CONSTEXPR array_view<ValueTypeOpt, RestDimensions...> operator[](size_type idx) const
|
||||||
{
|
{
|
||||||
@ -1937,6 +1946,7 @@ public:
|
|||||||
using typename Base::index_type;
|
using typename Base::index_type;
|
||||||
using typename Base::iterator;
|
using typename Base::iterator;
|
||||||
using typename Base::const_iterator;
|
using typename Base::const_iterator;
|
||||||
|
using typename Base::reference;
|
||||||
|
|
||||||
// from static array of size N
|
// from static array of size N
|
||||||
template<size_type N>
|
template<size_type N>
|
||||||
@ -1969,19 +1979,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert from bytes
|
// convert from bytes
|
||||||
template <typename OtherValueType, typename Dummy = std::enable_if_t<std::is_same<value_type, const byte>::value>>
|
template <typename OtherValueType>
|
||||||
strided_array_view<OtherValueType, rank> as_strided_array_view() const
|
strided_array_view<typename std::enable_if<std::is_same<value_type, const byte>::value, OtherValueType>::type, rank> as_strided_array_view() const
|
||||||
{
|
{
|
||||||
static_assert((sizeof(OtherValueType) >= sizeof(value_type)) && (sizeof(OtherValueType) % sizeof(value_type) == 0), "OtherValueType should have a size to contain a multiple of ValueTypes");
|
static_assert((sizeof(OtherValueType) >= sizeof(value_type)) && (sizeof(OtherValueType) % sizeof(value_type) == 0), "OtherValueType should have a size to contain a multiple of ValueTypes");
|
||||||
auto d = sizeof(OtherValueType) / sizeof(value_type);
|
auto d = sizeof(OtherValueType) / sizeof(value_type);
|
||||||
|
|
||||||
size_type size = bounds().total_size() / d;
|
size_type size = this->bounds().total_size() / d;
|
||||||
return{ (OtherValueType*)data(), size, bounds_type{ resize_extent(bounds().index_bounds(), d), resize_stride(bounds().strides(), d)} };
|
return{ (OtherValueType*)this->data(), size, bounds_type{ resize_extent(this->bounds().index_bounds(), d), resize_stride(this->bounds().strides(), d)} };
|
||||||
}
|
}
|
||||||
|
|
||||||
strided_array_view section(index_type origin, index_type extents) const
|
strided_array_view section(index_type origin, index_type extents) const
|
||||||
{
|
{
|
||||||
size_type size = bounds().total_size() - bounds().linearize(origin);
|
size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
|
||||||
return { &this->operator[](origin), size, bounds_type {extents, details::make_stride(Base::bounds())}};
|
return { &this->operator[](origin), size, bounds_type {extents, details::make_stride(Base::bounds())}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2271,4 +2281,9 @@ general_array_view_iterator<ArrayView> operator+(typename general_array_view_ite
|
|||||||
|
|
||||||
} // namespace Guide
|
} // namespace Guide
|
||||||
|
|
||||||
|
#if _MSC_VER <= 1800
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // _MSC_VER <= 1800
|
||||||
|
|
||||||
|
|
||||||
#pragma pop_macro("_NOEXCEPT")
|
#pragma pop_macro("_NOEXCEPT")
|
||||||
|
@ -27,13 +27,10 @@ namespace Guide
|
|||||||
//
|
//
|
||||||
#if defined(SAFER_CPP_TESTING)
|
#if defined(SAFER_CPP_TESTING)
|
||||||
|
|
||||||
struct fail_fast : public std::exception
|
struct fail_fast : public std::runtime_error
|
||||||
{
|
{
|
||||||
fail_fast() = default;
|
fail_fast() : std::runtime_error("") {}
|
||||||
|
explicit fail_fast(char const* const message) : std::runtime_error(message) {}
|
||||||
explicit fail_fast(char const* const message) :
|
|
||||||
std::exception(message)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void fail_fast_assert(bool cond) { if (!cond) throw fail_fast(); }
|
inline void fail_fast_assert(bool cond) { if (!cond) throw fail_fast(); }
|
||||||
|
@ -100,7 +100,7 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
// out of bounds
|
// out of bounds
|
||||||
CHECK_THROW(av[1][3] = 3, fail_fast);
|
CHECK_THROW(av[1][3] = 3, fail_fast);
|
||||||
CHECK_THROW((av[index<2>{1, 3}] = 3), fail_fast);
|
CHECK_THROW((av[{1, 3}] = 3), fail_fast);
|
||||||
|
|
||||||
CHECK_THROW(av[10][2], fail_fast);
|
CHECK_THROW(av[10][2], fail_fast);
|
||||||
CHECK_THROW((av[{10,2}]), fail_fast);
|
CHECK_THROW((av[{10,2}]), fail_fast);
|
||||||
@ -320,17 +320,29 @@ SUITE(array_view_tests)
|
|||||||
CHECK(sav.bounds().strides() == index<1>{ 1 });
|
CHECK(sav.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav[1] == 2);
|
CHECK(sav[1] == 2);
|
||||||
|
|
||||||
|
#if _MSC_VER > 1800
|
||||||
strided_array_view<const int, 1> sav_c{ {src}, {2, 1} };
|
strided_array_view<const int, 1> sav_c{ {src}, {2, 1} };
|
||||||
|
#else
|
||||||
|
strided_array_view<const int, 1> sav_c{ array_view<const int>{src}, strided_bounds<1>{2, 1} };
|
||||||
|
#endif
|
||||||
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 });
|
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 });
|
||||||
CHECK(sav_c.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_c.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_c[1] == 2);
|
CHECK(sav_c[1] == 2);
|
||||||
|
|
||||||
|
#if _MSC_VER > 1800
|
||||||
strided_array_view<volatile int, 1> sav_v{ {src}, {2, 1} };
|
strided_array_view<volatile int, 1> sav_v{ {src}, {2, 1} };
|
||||||
|
#else
|
||||||
|
strided_array_view<volatile int, 1> sav_v{ array_view<volatile int>{src}, strided_bounds<1>{2, 1} };
|
||||||
|
#endif
|
||||||
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 });
|
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 });
|
||||||
CHECK(sav_v.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_v.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_v[1] == 2);
|
CHECK(sav_v[1] == 2);
|
||||||
|
|
||||||
|
#if _MSC_VER > 1800
|
||||||
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
||||||
|
#else
|
||||||
|
strided_array_view<const volatile int, 1> sav_cv{ array_view<const volatile int>{src}, strided_bounds<1>{2, 1} };
|
||||||
|
#endif
|
||||||
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
||||||
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_cv[1] == 2);
|
CHECK(sav_cv[1] == 2);
|
||||||
@ -345,7 +357,12 @@ SUITE(array_view_tests)
|
|||||||
CHECK(sav_c.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_c.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_c[1] == 2);
|
CHECK(sav_c[1] == 2);
|
||||||
|
|
||||||
|
#if _MSC_VER > 1800
|
||||||
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
||||||
|
#else
|
||||||
|
strided_array_view<const volatile int, 1> sav_cv{ array_view<const volatile int>{src}, strided_bounds<1>{2, 1} };
|
||||||
|
#endif
|
||||||
|
|
||||||
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
||||||
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_cv[1] == 2);
|
CHECK(sav_cv[1] == 2);
|
||||||
@ -360,7 +377,11 @@ SUITE(array_view_tests)
|
|||||||
CHECK(sav_v.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_v.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_v[1] == 2);
|
CHECK(sav_v[1] == 2);
|
||||||
|
|
||||||
|
#if _MSC_VER > 1800
|
||||||
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
strided_array_view<const volatile int, 1> sav_cv{ {src}, {2, 1} };
|
||||||
|
#else
|
||||||
|
strided_array_view<const volatile int, 1> sav_cv{ array_view<const volatile int>{src}, strided_bounds<1>{2, 1} };
|
||||||
|
#endif
|
||||||
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
|
||||||
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
|
||||||
CHECK(sav_cv[1] == 2);
|
CHECK(sav_cv[1] == 2);
|
||||||
@ -621,14 +642,18 @@ SUITE(array_view_tests)
|
|||||||
// stride initializer list size should match the rank of the array
|
// stride initializer list size should match the rank of the array
|
||||||
CHECK_THROW((index<1>{ 0,1 }), fail_fast);
|
CHECK_THROW((index<1>{ 0,1 }), fail_fast);
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ arr, {1, {1,1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 1>{ arr, {1, {1,1}} }), fail_fast);
|
||||||
|
#ifdef _MSC_VER
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ arr, {{1,1 }, {1,1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 1>{ arr, {{1,1 }, {1,1}} }), fail_fast);
|
||||||
|
#endif
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {1, {1,1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 1>{ av, {1, {1,1}} }), fail_fast);
|
||||||
|
#ifdef _MSC_VER
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {{1,1 }, {1,1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 1>{ av, {{1,1 }, {1,1}} }), fail_fast);
|
||||||
|
#endif
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast);
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast);
|
||||||
|
#ifdef _MSC_VER
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast);
|
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -740,7 +765,6 @@ SUITE(array_view_tests)
|
|||||||
CHECK_THROW(empty_av[0], fail_fast);
|
CHECK_THROW(empty_av[0], fail_fast);
|
||||||
CHECK_THROW(empty_av.begin()[0], fail_fast);
|
CHECK_THROW(empty_av.begin()[0], fail_fast);
|
||||||
CHECK_THROW(empty_av.cbegin()[0], fail_fast);
|
CHECK_THROW(empty_av.cbegin()[0], fail_fast);
|
||||||
|
|
||||||
for (auto& v : empty_av)
|
for (auto& v : empty_av)
|
||||||
{
|
{
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
@ -749,12 +773,10 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
{
|
{
|
||||||
array_view<int> empty_av = {};
|
array_view<int> empty_av = {};
|
||||||
|
|
||||||
CHECK(empty_av.bounds().index_bounds() == index<1>{ 0 });
|
CHECK(empty_av.bounds().index_bounds() == index<1>{ 0 });
|
||||||
CHECK_THROW(empty_av[0], fail_fast);
|
CHECK_THROW(empty_av[0], fail_fast);
|
||||||
CHECK_THROW(empty_av.begin()[0], fail_fast);
|
CHECK_THROW(empty_av.begin()[0], fail_fast);
|
||||||
CHECK_THROW(empty_av.cbegin()[0], fail_fast);
|
CHECK_THROW(empty_av.cbegin()[0], fail_fast);
|
||||||
|
|
||||||
for (auto& v : empty_av)
|
for (auto& v : empty_av)
|
||||||
{
|
{
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
@ -803,13 +825,13 @@ SUITE(array_view_tests)
|
|||||||
array_view<int, dynamic_range> av(arr, 8);
|
array_view<int, dynamic_range> av(arr, 8);
|
||||||
|
|
||||||
size_t a[1] = { 0 };
|
size_t a[1] = { 0 };
|
||||||
index<1> i = index<1>(a);
|
index<1> i = a;
|
||||||
|
|
||||||
CHECK(av[i] == 4);
|
CHECK(av[i] == 4);
|
||||||
|
|
||||||
auto av2 = av.as_array_view(dim<4>(), dim<>(2));
|
auto av2 = av.as_array_view(dim<4>(), dim<>(2));
|
||||||
size_t a2[2] = { 0, 1 };
|
size_t a2[2] = { 0, 1 };
|
||||||
index<2> i2 = index<2>(a2);
|
index<2> i2 = a2;
|
||||||
|
|
||||||
CHECK(av2[i2] == 0);
|
CHECK(av2[i2] == 0);
|
||||||
CHECK(av2[0][i] == 4);
|
CHECK(av2[0][i] == 4);
|
||||||
@ -877,7 +899,8 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < section.size(); ++i)
|
for (unsigned int i = 0; i < section.size(); ++i)
|
||||||
{
|
{
|
||||||
CHECK(section[index<2>({ i,0 })] == av[i][1]);
|
auto idx = index<2>{ i,0 }; // avoid braces inside the CHECK macro
|
||||||
|
CHECK(section[idx] == av[i][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK(section.bounds().index_bounds()[0] == length);
|
CHECK(section.bounds().index_bounds()[0] == length);
|
||||||
@ -886,11 +909,12 @@ SUITE(array_view_tests)
|
|||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < section.bounds().index_bounds()[1]; ++j)
|
for (unsigned int j = 0; j < section.bounds().index_bounds()[1]; ++j)
|
||||||
{
|
{
|
||||||
CHECK(section[index<2>({ i,j })] == av[i][1]);
|
auto idx = index<2>{ i,j }; // avoid braces inside the CHECK macro
|
||||||
|
CHECK(section[idx] == av[i][1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int idx = 0;
|
size_t idx = 0;
|
||||||
for (auto num : section)
|
for (auto num : section)
|
||||||
{
|
{
|
||||||
CHECK(num == av[idx][1]);
|
CHECK(num == av[idx][1]);
|
||||||
@ -961,7 +985,11 @@ SUITE(array_view_tests)
|
|||||||
// pick every other element
|
// pick every other element
|
||||||
|
|
||||||
auto length = av.size() / 2;
|
auto length = av.size() / 2;
|
||||||
|
#if _MSC_VER > 1800
|
||||||
auto bounds = strided_bounds<1>({ length }, { 2 });
|
auto bounds = strided_bounds<1>({ length }, { 2 });
|
||||||
|
#else
|
||||||
|
auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 });
|
||||||
|
#endif
|
||||||
strided_array_view<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
|
strided_array_view<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
|
||||||
|
|
||||||
CHECK(strided.size() == length);
|
CHECK(strided.size() == length);
|
||||||
@ -1020,7 +1048,10 @@ SUITE(array_view_tests)
|
|||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < section.extent<1>(); ++j)
|
for (unsigned int j = 0; j < section.extent<1>(); ++j)
|
||||||
for (unsigned int k = 0; k < section.extent<2>(); ++k)
|
for (unsigned int k = 0; k < section.extent<2>(); ++k)
|
||||||
CHECK(section[index<3>({ i,j,k })] == expected[2 * i + 2 * j + k]);
|
{
|
||||||
|
auto idx = index<3>{ i,j,k }; // avoid braces in the CHECK macro
|
||||||
|
CHECK(section[idx] == expected[2 * i + 2 * j + k]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < section.extent<0>(); ++i)
|
for (unsigned int i = 0; i < section.extent<0>(); ++i)
|
||||||
|
Loading…
Reference in New Issue
Block a user