aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/byte.h33
-rw-r--r--include/multi_span.h4
-rw-r--r--include/span.h34
-rw-r--r--tests/span_tests.cpp91
4 files changed, 124 insertions, 38 deletions
diff --git a/include/byte.h b/include/byte.h
new file mode 100644
index 0000000..c6449aa
--- /dev/null
+++ b/include/byte.h
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#ifndef GSL_BYTE_H
+#define GSL_BYTE_H
+
+namespace gsl
+{
+ // This is a simple definition for now that allows
+ // use of byte within span<> to be standards-compliant
+ //
+ // Ultimately a small language change would allow a more
+ // robust definition (see WG21 proposal P0257 for details).
+ using byte = unsigned char;
+
+} // namespace gsl
+
+#endif // GSL_BYTE_H \ No newline at end of file
diff --git a/include/multi_span.h b/include/multi_span.h
index 523f324..3d00c6e 100644
--- a/include/multi_span.h
+++ b/include/multi_span.h
@@ -21,6 +21,7 @@
#include "gsl_assert.h"
#include "gsl_util.h"
+#include "byte.h"
#include <algorithm>
#include <array>
#include <cassert>
@@ -1053,9 +1054,6 @@ template <typename Span>
class contiguous_span_iterator;
template <typename Span>
class general_span_iterator;
-enum class byte : std::uint8_t
-{
-};
template <std::ptrdiff_t DimSize = dynamic_range>
struct dim
diff --git a/include/span.h b/include/span.h
index 2760121..7152c2d 100644
--- a/include/span.h
+++ b/include/span.h
@@ -21,6 +21,7 @@
#include "gsl_assert.h"
#include "gsl_util.h"
+#include "byte.h"
#include <array>
#include <limits>
#include <iterator>
@@ -126,13 +127,13 @@ struct is_allowed_element_type_conversion
};
template <class From>
-struct is_allowed_element_type_conversion<From, char>
+struct is_allowed_element_type_conversion<From, byte>
: std::integral_constant<bool, !std::is_const<From>::value>
{
};
template <class From>
-struct is_allowed_element_type_conversion<From, const char>
+struct is_allowed_element_type_conversion<From, const byte>
: std::integral_constant<bool, true>
{
};
@@ -507,14 +508,33 @@ constexpr bool operator>=(const span<ElementType, Extent>& l, const span<Element
{ return !(l < r); }
-#if 0 // TODO
+namespace details
+{
+ // if we only supported compilers with good constexpr support then
+ // this pair of classes could collapse down to a constexpr function
+
+ // we should use a narrow_cast<> to go to size_t, but older compilers may not see it as constexpr
+ // and so will fail compilation of the template
+ template <class ElementType, ptrdiff_t Extent>
+ struct calculate_byte_size :
+ std::integral_constant<std::ptrdiff_t, static_cast<ptrdiff_t>(sizeof(ElementType) * static_cast<size_t>(Extent))>
+ {};
+
+ template <class ElementType>
+ struct calculate_byte_size<ElementType, dynamic_extent> :
+ std::integral_constant<std::ptrdiff_t, dynamic_extent>
+ {};
+}
+
+
// [span.objectrep], views of object representation
template <class ElementType, ptrdiff_t Extent>
-constexpr span<const char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
+constexpr span<const byte, details::calculate_byte_size<ElementType, Extent>::value> as_bytes(span<ElementType, Extent> s) noexcept
+{ return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; }
-template <class ElementType, ptrdiff_t Extent>
-constexpr span<char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_writeable_bytes(span<ElementType, Extent>) noexcept;
-#endif
+template <class ElementType, ptrdiff_t Extent, class = std::enable_if_t<!std::is_const<ElementType>::value>>
+constexpr span<byte, details::calculate_byte_size<ElementType, Extent>::value> as_writeable_bytes(span<ElementType, Extent> s) noexcept
+{ return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; }
} // namespace gsl
diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp
index 694d9a2..ddae404 100644
--- a/tests/span_tests.cpp
+++ b/tests/span_tests.cpp
@@ -921,6 +921,69 @@ SUITE(span_tests)
}
}
+ TEST(as_bytes)
+ {
+ int a[] = {1, 2, 3, 4};
+
+ {
+ span<const int> s = a;
+ CHECK(s.length() == 4);
+ span<const byte> bs = as_bytes(s);
+ CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ CHECK(bs.length() == s.length_bytes());
+ }
+
+ {
+ span<int> s;
+ auto bs = as_bytes(s);
+ CHECK(bs.length() == s.length());
+ CHECK(bs.length() == 0);
+ CHECK(bs.size_bytes() == 0);
+ CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ CHECK(bs.data() == nullptr);
+ }
+
+ {
+ span<int> s = a;
+ auto bs = as_bytes(s);
+ CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ CHECK(bs.length() == s.length_bytes());
+ }
+ }
+
+ TEST(as_writeable_bytes)
+ {
+ int a[] = {1, 2, 3, 4};
+
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ // you should not be able to get writeable bytes for const objects
+ span<const int> s = a;
+ CHECK(s.length() == 4);
+ span<const byte> bs = as_writeable_bytes(s);
+ CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ CHECK(bs.length() == s.length_bytes());
+#endif
+ }
+
+ {
+ span<int> s;
+ auto bs = as_writeable_bytes(s);
+ CHECK(bs.length() == s.length());
+ CHECK(bs.length() == 0);
+ CHECK(bs.size_bytes() == 0);
+ CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ CHECK(bs.data() == nullptr);
+ }
+
+ {
+ span<int> s = a;
+ auto bs = as_writeable_bytes(s);
+ CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ CHECK(bs.length() == s.length_bytes());
+ }
+ }
+
#if 0
TEST(fixed_size_conversions)
{
@@ -1018,34 +1081,6 @@ SUITE(span_tests)
CHECK_THROW(f(), fail_fast);
}
- TEST(as_writeable_bytes)
- {
- int a[] = {1, 2, 3, 4};
-
- {
-#ifdef CONFIRM_COMPILATION_ERRORS
- // you should not be able to get writeable bytes for const objects
- span<const int, dynamic_range> av = a;
- auto wav = av.as_writeable_bytes();
-#endif
- }
-
- {
- span<int, dynamic_range> av;
- auto wav = as_writeable_bytes(av);
- CHECK(wav.length() == av.length());
- CHECK(wav.length() == 0);
- CHECK(wav.size_bytes() == 0);
- }
-
- {
- span<int, dynamic_range> av = a;
- auto wav = as_writeable_bytes(av);
- CHECK(wav.data() == (byte*) &a[0]);
- CHECK(wav.length() == sizeof(a));
- }
- }
-
#endif
}