[span] Tell MSVC how to avoid range-checking (#664)

* [span] implement non-member + as a hidden friend

Drive-by: remove garbage `operator-(difference_type, span_iterator)`.

* [span] Use pointers for range-based-for on MSVC
This commit is contained in:
Casey Carter 2018-05-09 14:01:22 -07:00 committed by Anna Gringauze
parent 5cbde3008a
commit d6a2242d97

View File

@ -191,6 +191,11 @@ namespace details
return ret += n; return ret += n;
} }
friend constexpr span_iterator operator+(difference_type n, span_iterator const& rhs)
{
return rhs + n;
}
constexpr span_iterator& operator+=(difference_type n) constexpr span_iterator& operator+=(difference_type n)
{ {
Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
@ -258,22 +263,6 @@ namespace details
std::ptrdiff_t index_ = 0; std::ptrdiff_t index_ = 0;
}; };
template <class Span, bool IsConst>
constexpr span_iterator<Span, IsConst>
operator+(typename span_iterator<Span, IsConst>::difference_type n,
span_iterator<Span, IsConst> rhs)
{
return rhs + n;
}
template <class Span, bool IsConst>
constexpr span_iterator<Span, IsConst>
operator-(typename span_iterator<Span, IsConst>::difference_type n,
span_iterator<Span, IsConst> rhs)
{
return rhs - n;
}
template <std::ptrdiff_t Ext> template <std::ptrdiff_t Ext>
class extent_type class extent_type
{ {
@ -418,7 +407,7 @@ public:
~span() noexcept = default; ~span() noexcept = default;
constexpr span& operator=(const span& other) noexcept = default; constexpr span& operator=(const span& other) noexcept = default;
// [span.sub], span subviews // [span.sub], span subviews
template <std::ptrdiff_t Count> template <std::ptrdiff_t Count>
constexpr span<element_type, Count> first() const constexpr span<element_type, Count> first() const
@ -493,10 +482,16 @@ public:
constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; }
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; }
#ifdef _MSC_VER
// Tell MSVC how to unwrap spans in range-based-for
constexpr pointer _Unchecked_begin() const noexcept { return data(); }
constexpr pointer _Unchecked_end() const noexcept { return data() + size(); }
#endif // _MSC_VER
private: private:
// Needed to remove unnecessary null check in subspans // Needed to remove unnecessary null check in subspans
struct KnownNotNull struct KnownNotNull
{ {
pointer p; pointer p;
}; };
@ -508,7 +503,7 @@ private:
class storage_type : public ExtentType class storage_type : public ExtentType
{ {
public: public:
// KnownNotNull parameter is needed to remove unnecessary null check // KnownNotNull parameter is needed to remove unnecessary null check
// in subspans and constructors from arrays // in subspans and constructors from arrays
template <class OtherExtentType> template <class OtherExtentType>
constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p)