mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Fix return type of templated span.subspan() (#625)
* Added support for returning fixed-spize spans from subspan(). * Addressed issues from code review. * Took simpler approach to static data member. * Subtle fix to support MSVC 15. * Helps to not introduce extraneous >
This commit is contained in:
parent
cbd64c9ff6
commit
6a33b97a84
@ -45,8 +45,17 @@
|
|||||||
#if _MSC_VER < 1910
|
#if _MSC_VER < 1910
|
||||||
#pragma push_macro("constexpr")
|
#pragma push_macro("constexpr")
|
||||||
#define constexpr /*constexpr*/
|
#define constexpr /*constexpr*/
|
||||||
|
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
|
||||||
|
|
||||||
#endif // _MSC_VER < 1910
|
#endif // _MSC_VER < 1910
|
||||||
|
#else // _MSC_VER
|
||||||
|
|
||||||
|
// See if we have enough C++17 power to use a static constexpr data member
|
||||||
|
// without needing an out-of-line definition
|
||||||
|
#if !(defined(__cplusplus) && (__cplusplus >= 201703L))
|
||||||
|
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
|
||||||
|
#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#define GSL_NOEXCEPT noexcept
|
#define GSL_NOEXCEPT noexcept
|
||||||
@ -302,6 +311,12 @@ namespace details
|
|||||||
private:
|
private:
|
||||||
index_type size_;
|
index_type size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count>
|
||||||
|
struct calculate_subspan_type
|
||||||
|
{
|
||||||
|
using type = span<ElementType, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : Extent)>;
|
||||||
|
};
|
||||||
} // namespace details
|
} // namespace details
|
||||||
|
|
||||||
// [span], class template span
|
// [span], class template span
|
||||||
@ -323,7 +338,11 @@ public:
|
|||||||
|
|
||||||
using size_type = index_type;
|
using size_type = index_type;
|
||||||
|
|
||||||
constexpr static const index_type extent = Extent;
|
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||||
|
static constexpr const index_type extent { Extent };
|
||||||
|
#else
|
||||||
|
static constexpr index_type extent { Extent };
|
||||||
|
#endif
|
||||||
|
|
||||||
// [span.cons], span constructors, copy, assignment, and destructor
|
// [span.cons], span constructors, copy, assignment, and destructor
|
||||||
template <bool Dependent = false,
|
template <bool Dependent = false,
|
||||||
@ -412,7 +431,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
|
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
|
||||||
constexpr span<element_type, Count> subspan() const
|
constexpr auto subspan() const -> typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
|
||||||
{
|
{
|
||||||
Expects((Offset >= 0 && size() - Offset >= 0) &&
|
Expects((Offset >= 0 && size() - Offset >= 0) &&
|
||||||
(Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));
|
(Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));
|
||||||
@ -525,6 +544,11 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||||
|
template <class ElementType, std::ptrdiff_t Extent>
|
||||||
|
constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// [span.comparison], span comparison operators
|
// [span.comparison], span comparison operators
|
||||||
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
|
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
|
||||||
|
@ -776,6 +776,7 @@ TEST_CASE("subspan")
|
|||||||
{
|
{
|
||||||
span<int, 5> av = arr;
|
span<int, 5> av = arr;
|
||||||
CHECK((av.subspan<2, 2>().size() == 2));
|
CHECK((av.subspan<2, 2>().size() == 2));
|
||||||
|
CHECK(decltype(av.subspan<2, 2>())::extent == 2);
|
||||||
CHECK(av.subspan(2, 2).size() == 2);
|
CHECK(av.subspan(2, 2).size() == 2);
|
||||||
CHECK(av.subspan(2, 3).size() == 3);
|
CHECK(av.subspan(2, 3).size() == 3);
|
||||||
}
|
}
|
||||||
@ -783,13 +784,16 @@ TEST_CASE("subspan")
|
|||||||
{
|
{
|
||||||
span<int, 5> av = arr;
|
span<int, 5> av = arr;
|
||||||
CHECK((av.subspan<0, 0>().size() == 0));
|
CHECK((av.subspan<0, 0>().size() == 0));
|
||||||
|
CHECK(decltype(av.subspan<0,0>())::extent == 0);
|
||||||
CHECK(av.subspan(0, 0).size() == 0);
|
CHECK(av.subspan(0, 0).size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
span<int, 5> av = arr;
|
span<int, 5> av = arr;
|
||||||
CHECK((av.subspan<0, 5>().size() == 5));
|
CHECK((av.subspan<0, 5>().size() == 5));
|
||||||
|
CHECK(decltype(av.subspan<0, 5>())::extent == 5);
|
||||||
CHECK(av.subspan(0, 5).size() == 5);
|
CHECK(av.subspan(0, 5).size() == 5);
|
||||||
|
|
||||||
CHECK_THROWS_AS(av.subspan(0, 6).size(), fail_fast);
|
CHECK_THROWS_AS(av.subspan(0, 6).size(), fail_fast);
|
||||||
CHECK_THROWS_AS(av.subspan(1, 5).size(), fail_fast);
|
CHECK_THROWS_AS(av.subspan(1, 5).size(), fail_fast);
|
||||||
}
|
}
|
||||||
@ -797,14 +801,22 @@ TEST_CASE("subspan")
|
|||||||
{
|
{
|
||||||
span<int, 5> av = arr;
|
span<int, 5> av = arr;
|
||||||
CHECK((av.subspan<4, 0>().size() == 0));
|
CHECK((av.subspan<4, 0>().size() == 0));
|
||||||
|
CHECK(decltype(av.subspan<4, 0>())::extent == 0);
|
||||||
CHECK(av.subspan(4, 0).size() == 0);
|
CHECK(av.subspan(4, 0).size() == 0);
|
||||||
CHECK(av.subspan(5, 0).size() == 0);
|
CHECK(av.subspan(5, 0).size() == 0);
|
||||||
CHECK_THROWS_AS(av.subspan(6, 0).size(), fail_fast);
|
CHECK_THROWS_AS(av.subspan(6, 0).size(), fail_fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
span<int, 5> av = arr;
|
||||||
|
CHECK((av.subspan<1>().size() == 4));
|
||||||
|
CHECK(decltype(av.subspan<1>())::extent == 4);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
span<int> av;
|
span<int> av;
|
||||||
CHECK((av.subspan<0, 0>().size() == 0));
|
CHECK((av.subspan<0, 0>().size() == 0));
|
||||||
|
CHECK((decltype(av.subspan<0, 0>())::extent == 0));
|
||||||
CHECK(av.subspan(0, 0).size() == 0);
|
CHECK(av.subspan(0, 0).size() == 0);
|
||||||
CHECK_THROWS_AS((av.subspan<1, 0>().size()), fail_fast);
|
CHECK_THROWS_AS((av.subspan<1, 0>().size()), fail_fast);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user