diff options
-rw-r--r-- | include/string_span.h | 142 | ||||
-rw-r--r-- | tests/string_span_tests.cpp | 40 |
2 files changed, 76 insertions, 106 deletions
diff --git a/include/string_span.h b/include/string_span.h index 44a3f56..c9a4dc9 100644 --- a/include/string_span.h +++ b/include/string_span.h @@ -34,8 +34,9 @@ #if _MSC_VER <= 1800 #define GSL_MSVC_HAS_TYPE_DEDUCTION_BUG -#define GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER -#define GSL_MSVC2013_EQUAL_ALGORITHM_IS_NOT_CPP14 +#define GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE +#define GSL_MSVC_NO_CPP14_STD_EQUAL +#define GSL_MSVC_NO_DEFAULT_MOVE_CTOR // noexcept is not understood #ifndef GSL_THROW_ON_CONTRACT_VIOLATION @@ -237,27 +238,26 @@ public: constexpr basic_string_span(const basic_string_span& other) = default; // move -#ifdef GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT - constexpr basic_string_span(basic_string_span&& other) - : span_(std::move(other.span_)) - { - } -#else +#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_string_span(basic_string_span&& other) = default; +#else + constexpr basic_string_span(basic_string_span&& other) + : span_(std::move(other.span_)) + {} #endif // assign constexpr basic_string_span& operator=(const basic_string_span& other) = default; // 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 +#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_string_span& operator=(basic_string_span&& other) = default; +#else + constexpr basic_string_span& operator=(basic_string_span&& other) + { + span_ = std::move(other.span_); + return *this; + } #endif // from nullptr @@ -290,74 +290,6 @@ public: : 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 template <typename Cont, typename DataType = typename Cont::value_type, typename Dummy = std::enable_if_t<!details::is_span<Cont>::value @@ -379,14 +311,27 @@ public: > basic_string_span(Cont&& cont) = delete; +#ifndef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE // from span template <typename OtherValueType, std::ptrdiff_t OtherExtent, - typename OtherBounds = static_bounds<OtherExtent>, - typename Dummy = std::enable_if_t<std::is_convertible<OtherValueType*, value_type*>::value && std::is_convertible<OtherBounds, bounds_type>::value> + typename Dummy = std::enable_if_t< + std::is_convertible<OtherValueType*, value_type*>::value + && std::is_convertible<static_bounds<OtherExtent>, bounds_type>::value> > constexpr basic_string_span(span<OtherValueType, OtherExtent> other) noexcept : span_(other) {} +#else + // from span + constexpr basic_string_span(span<value_type, Extent> other) noexcept + : span_(other) + {} + + template <typename Dummy = std::enable_if_t<!std::is_same<std::remove_const_t<value_type>, value_type>::value>> + constexpr basic_string_span(span<std::remove_const_t<value_type>, Extent> other) noexcept + : span_(other) + {} +#endif // from string_span template <typename OtherValueType, std::ptrdiff_t OtherExtent, @@ -396,7 +341,6 @@ public: constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept : span_(other.data(), other.length()) {} -#endif // GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER constexpr bool empty() const noexcept { @@ -556,22 +500,22 @@ std::basic_string<typename std::remove_const<CharT>::type> to_string(basic_strin inline std::string to_string(cstring_span<> view) { - return{ view.data(), view.length() }; + return{ view.data(), static_cast<size_t>(view.length()) }; } inline std::string to_string(string_span<> view) { - return{ view.data(), view.length() }; + return{ view.data(), static_cast<size_t>(view.length()) }; } inline std::wstring to_string(cwstring_span<> view) { - return{ view.data(), view.length() }; + return{ view.data(), static_cast<size_t>(view.length()) }; } inline std::wstring to_string(wstring_span<> view) { - return{ view.data(), view.length() }; + return{ view.data(), static_cast<size_t>(view.length()) }; } #endif @@ -622,10 +566,8 @@ template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept { gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); -#ifdef GSL_MSVC2013_EQUAL_ALGORITHM_IS_NOT_CPP14 - if (std::distance(one.begin(), one.end()) != std::distance(tmp.begin(), tmp.end())) - return false; - return std::equal(one.begin(), one.end(), tmp.begin()); +#ifdef GSL_MSVC_NO_CPP14_STD_EQUAL + return (one.size() == tmp.size()) && std::equal(one.begin(), one.end(), tmp.begin()); #else return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); #endif @@ -639,10 +581,8 @@ template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept { gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); -#ifdef GSL_MSVC2013_EQUAL_ALGORITHM_IS_NOT_CPP14 - if (std::distance(tmp.begin(), tmp.end()) != std::distance(other.begin(), other.end())) - return false; - return std::equal(tmp.begin(), tmp.end(), other.begin()); +#ifdef GSL_MSVC_NO_CPP14_STD_EQUAL + return (tmp.size() == other.size()) && std::equal(tmp.begin(), tmp.end(), other.begin()); #else return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end()); #endif @@ -959,9 +899,10 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc #pragma pop_macro("noexcept") #endif // GSL_THROW_ON_CONTRACT_VIOLATION -#undef GSL_MSVC2013_EQUAL_ALGORITHM_IS_NOT_CPP14 -#undef GSL_MSVC2013_ICE_WHEN_USING_DUMMY_TEMPLATE_PARAMETER #undef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG +#undef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE +#define GSL_MSVC_NO_CPP14_STD_EQUAL +#undef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #endif // _MSC_VER <= 1800 #endif // _MSC_VER @@ -975,5 +916,4 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc #endif #endif // GSL_THROW_ON_CONTRACT_VIOLATION - #endif // GSL_STRING_SPAN_H diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index 18fda26..88d125a 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -29,7 +29,6 @@ SUITE(string_span_tests) TEST(TestLiteralConstruction) { cwstring_span<> v = ensure_z(L"Hello"); - CHECK(5 == v.length()); #ifdef CONFIRM_COMPILATION_ERRORS @@ -118,6 +117,24 @@ SUITE(string_span_tests) { { cstring_span<> span = "Hello"; + cstring_span<> span1; + + // comparison to empty span + CHECK(span1 != span); + CHECK(span != span1); + } + + { + cstring_span<> span = "Hello"; + cstring_span<> span1 = "Hello1"; + + // comparison to different span + CHECK(span1 != span); + CHECK(span != span1); + } + + { + cstring_span<> span = "Hello"; const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar1[] = "Hello"; @@ -153,9 +170,6 @@ SUITE(string_span_tests) // comparison to string_span CHECK(span == span); - - // comparison of the original data to string - CHECK(span.data() == std::string("Hello")); } { @@ -431,6 +445,22 @@ SUITE(string_span_tests) { // creating cstring_span + // from span of a final extent + { + span<const char, 6> sp = "Hello"; + cstring_span<> span = sp; + CHECK(span.length() == 6); + } + + // from const span of a final extent to non-const string_span +#ifdef CONFIRM_COMPILATION_ERRORS + { + span<const char, 6> sp = "Hello"; + string_span<> span = sp; + CHECK(span.length() == 6); + } +#endif + // from string temporary #ifdef CONFIRM_COMPILATION_ERRORS { @@ -794,7 +824,7 @@ SUITE(string_span_tests) TEST(Conversion) { -#ifdef CONFIRM_COMPPILATION_ERRORS +#ifdef CONFIRM_COMPILATION_ERRORS cstring_span<> span = "Hello"; cwstring_span<> wspan{ span }; CHECK(wspan.length() == 5); |