Merge branch 'VS2013-fix-string_span-ctors' of https://github.com/menuet/GSL into menuet-VS2013-fix-string_span-ctors

This commit is contained in:
Neil MacIntosh 2015-12-14 11:08:58 -08:00
commit 385780388e
2 changed files with 97 additions and 2 deletions

View File

@ -45,6 +45,12 @@
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr #define constexpr
// On Windows, if NOMINMAX is not defined, then windows.h defines the macro max
#ifdef _WIN32
#pragma push_macro("max")
#define max max
#endif
// VS 2013 workarounds // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
@ -2196,6 +2202,11 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#ifdef _WIN32
#undef max
#pragma pop_macro("max")
#endif
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#pragma warning(pop) #pragma warning(pop)

View File

@ -34,6 +34,7 @@
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#define GSL_MSVC_HAS_TYPE_DEDUCTION_BUG #define GSL_MSVC_HAS_TYPE_DEDUCTION_BUG
#define GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER
// noexcept is not understood // noexcept is not understood
#ifndef GSL_THROW_ON_CONTRACT_VIOLATION #ifndef GSL_THROW_ON_CONTRACT_VIOLATION
@ -235,13 +236,28 @@ public:
constexpr basic_string_span(const basic_string_span& other) = default; constexpr basic_string_span(const basic_string_span& other) = default;
// move // move
#ifdef GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
constexpr basic_string_span(basic_string_span&& other)
: span_(std::move(other.span_))
{
}
#else
constexpr basic_string_span(basic_string_span&& other) = default; constexpr basic_string_span(basic_string_span&& other) = default;
#endif
// assign // assign
constexpr basic_string_span& operator=(const basic_string_span& other) = default; constexpr basic_string_span& operator=(const basic_string_span& other) = default;
// move assign // move assign
#ifdef GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
constexpr basic_string_span& operator=(basic_string_span&& other)
{
span_ = std::move(other.span_);
return *this;
}
#else
constexpr basic_string_span& operator=(basic_string_span&& other) = default; constexpr basic_string_span& operator=(basic_string_span&& other) = default;
#endif
// from nullptr // from nullptr
constexpr basic_string_span(std::nullptr_t ptr) noexcept constexpr basic_string_span(std::nullptr_t ptr) noexcept
@ -273,6 +289,74 @@ public:
: span_(const_cast<pointer>(s.data()), narrow_cast<std::ptrdiff_t>(s.length())) : span_(const_cast<pointer>(s.data()), narrow_cast<std::ptrdiff_t>(s.length()))
{} {}
#ifdef GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER
template<
typename Cont,
typename DataType = typename Cont::value_type
>
constexpr basic_string_span(
Cont& cont,
std::enable_if_t<
!details::is_span<Cont>::value
&& !details::is_basic_string_span<Cont>::value
&& !(!std::is_const<value_type>::value && std::is_const<Cont>::value)
&& std::is_convertible<DataType*, value_type*>::value
&& std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), *std::declval<Cont>().data())>, DataType>::value
>* = nullptr
)
: span_(cont.data(), cont.size())
{}
// disallow creation from temporary containers and strings
template<
typename Cont,
typename DataType = typename Cont::value_type
>
explicit basic_string_span(
Cont&& cont
,
std::enable_if_t<
!details::is_span<Cont>::value
&& !details::is_basic_string_span<Cont>::value
&& std::is_convertible<DataType*, value_type*>::value
&& std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), *std::declval<Cont>().data())>, DataType>::value
>* = nullptr
) = delete;
// from span
template<
typename OtherValueType,
std::ptrdiff_t... OtherDimensions,
typename OtherBounds = static_bounds<OtherDimensions...>
>
constexpr basic_string_span(
span<OtherValueType, OtherDimensions...> other,
typename std::enable_if<
std::is_convertible<OtherValueType, value_type>::value &&
std::is_convertible<OtherBounds, bounds_type>::value
>::type* = nullptr
) noexcept
: span_(other)
{}
// from string_span
template<
typename OtherValueType,
std::ptrdiff_t OtherExtent,
typename OtherBounds = static_bounds<OtherExtent>
>
constexpr basic_string_span(
basic_string_span<OtherValueType, OtherExtent> other,
std::enable_if_t<
std::is_convertible<OtherValueType*, value_type*>::value
&& std::is_convertible<OtherBounds, bounds_type>::value
>* = nullptr
) noexcept
: span_(other.data(), other.length())
{}
#else // GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER
// from containers. Containers must have .size() and .data() function signatures // from containers. Containers must have .size() and .data() function signatures
template <typename Cont, typename DataType = typename Cont::value_type, template <typename Cont, typename DataType = typename Cont::value_type,
typename Dummy = std::enable_if_t<!details::is_span<Cont>::value typename Dummy = std::enable_if_t<!details::is_span<Cont>::value
@ -311,6 +395,7 @@ public:
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept
: span_(other.data(), other.length()) : span_(other.data(), other.length())
{} {}
#endif // GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER
constexpr bool empty() const noexcept constexpr bool empty() const noexcept
{ {
@ -856,13 +941,12 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#pragma warning(pop)
#ifndef GSL_THROW_ON_CONTRACT_VIOLATION #ifndef GSL_THROW_ON_CONTRACT_VIOLATION
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#endif // GSL_THROW_ON_CONTRACT_VIOLATION #endif // GSL_THROW_ON_CONTRACT_VIOLATION
#undef GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER
#undef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG #undef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800