From 2df9f85385ef5cfa06b5b549d73ca9ff5fa23abd Mon Sep 17 00:00:00 2001 From: Rian Quinn Date: Wed, 16 Nov 2016 11:17:04 -0700 Subject: [PATCH] Add make_span() This patch provides a make_span function to simplify the creation of spans until C++17 is available. In addition this patch updates the unit tests to includes tests that verify this new functionality. --- gsl/span | 39 +++++++++++++++ tests/span_tests.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/gsl/span b/gsl/span index 0925344..6d6992d 100644 --- a/gsl/span +++ b/gsl/span @@ -632,6 +632,45 @@ as_writeable_bytes(span s) noexcept return {reinterpret_cast(s.data()), s.size_bytes()}; } +// +// make_span() - Utility functions for creating spans +// +template +span +make_span(ElementType* ptr, typename span::index_type count) +{ return span(ptr, count); } + +template +span +make_span(ElementType* firstElem, ElementType* lastElem) +{ return span(firstElem, lastElem); } + +template +span +make_span(ElementType (&arr)[N]) +{ return span(arr); } + +template +span +make_span(Container &cont) +{ return span(cont); } + +template +span +make_span(const Container &cont) +{ return span(cont); } + +template +span +make_span(Ptr& cont, std::ptrdiff_t count) +{ return span(cont, count); } + +template +span +make_span(Ptr& cont) +{ return span(cont); } + + // Specialization of gsl::at for span template constexpr ElementType& at(const span& s, std::ptrdiff_t index) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 959dde0..9669464 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -204,6 +204,24 @@ SUITE(span_tests) auto workaround_macro = [=]() { span s{p, 2}; }; CHECK_THROW(workaround_macro(), fail_fast); } + + { + auto s = make_span(&arr[0], 2); + CHECK(s.length() == 2 && s.data() == &arr[0]); + CHECK(s[0] == 1 && s[1] == 2); + } + + { + int* p = nullptr; + auto s = make_span(p, static_cast::index_type>(0)); + CHECK(s.length() == 0 && s.data() == nullptr); + } + + { + int* p = nullptr; + auto workaround_macro = [=]() { make_span(p, 2); }; + CHECK_THROW(workaround_macro(), fail_fast); + } } TEST(from_pointer_pointer_constructor) @@ -263,6 +281,23 @@ SUITE(span_tests) // auto workaround_macro = [&]() { span s{&arr[0], p}; }; // CHECK_THROW(workaround_macro(), fail_fast); //} + + { + auto s = make_span(&arr[0], &arr[2]); + CHECK(s.length() == 2 && s.data() == &arr[0]); + CHECK(s[0] == 1 && s[1] == 2); + } + + { + auto s = make_span(&arr[0], &arr[0]); + CHECK(s.length() == 0 && s.data() == &arr[0]); + } + + { + int* p = nullptr; + auto s = make_span(p, p); + CHECK(s.length() == 0 && s.data() == nullptr); + } } TEST(from_array_constructor) @@ -339,6 +374,21 @@ SUITE(span_tests) span s{&arr3d[0], 1}; CHECK(s.length() == 1 && s.data() == &arr3d[0]); } + + { + auto s = make_span(arr); + CHECK(s.length() == 5 && s.data() == &arr[0]); + } + + { + auto s = make_span(&(arr2d[0]), 1); + CHECK(s.length() == 1 && s.data() == &arr2d[0]); + } + + { + auto s = make_span(&arr3d[0], 1); + CHECK(s.length() == 1 && s.data() == &arr3d[0]); + } } TEST(from_dynamic_array_constructor) @@ -350,6 +400,11 @@ SUITE(span_tests) CHECK(s.length() == 10 && s.data() == &arr[0][0][0]); } + { + auto s = make_span(&arr[0][0][0], 10); + CHECK(s.length() == 10 && s.data() == &arr[0][0][0]); + } + delete[] arr; } @@ -408,6 +463,11 @@ SUITE(span_tests) // try to take a temporary std::array take_a_span(get_an_array()); } + + { + auto s = make_span(arr); + CHECK(s.size() == narrow_cast(arr.size()) && s.data() == arr.data()); + } } TEST(from_const_std_array_constructor) @@ -446,6 +506,11 @@ SUITE(span_tests) // try to take a temporary std::array take_a_span(get_an_array()); } + + { + auto s = make_span(arr); + CHECK(s.size() == narrow_cast(arr.size()) && s.data() == arr.data()); + } } TEST(from_std_array_const_constructor) @@ -481,6 +546,11 @@ SUITE(span_tests) span s{arr}; } #endif + + { + auto s = make_span(arr); + CHECK(s.size() == narrow_cast(arr.size()) && s.data() == arr.data()); + } } TEST(from_unique_pointer_construction) @@ -493,6 +563,12 @@ SUITE(span_tests) CHECK(s.length() == 1 && s.data() == ptr.get()); CHECK(s[0] == 4); } + + { + auto s = make_span(ptr); + CHECK(s.length() == 1 && s.data() == ptr.get()); + CHECK(s[0] == 4); + } } { @@ -502,6 +578,11 @@ SUITE(span_tests) span s{ptr}; CHECK(s.length() == 0 && s.data() == nullptr); } + + { + auto s = make_span(ptr); + CHECK(s.length() == 0 && s.data() == nullptr); + } } { @@ -515,13 +596,24 @@ SUITE(span_tests) CHECK(s.length() == 4 && s.data() == arr.get()); CHECK(s[0] == 1 && s[1] == 2); } + + { + auto s = make_span(arr, 4); + CHECK(s.length() == 4 && s.data() == arr.get()); + CHECK(s[0] == 1 && s[1] == 2); + } } { - auto ptr = std::unique_ptr{nullptr}; + auto arr = std::unique_ptr{nullptr}; { - span s{ptr, 0}; + span s{arr, 0}; + CHECK(s.length() == 0 && s.data() == nullptr); + } + + { + auto s = make_span(arr, 0); CHECK(s.length() == 0 && s.data() == nullptr); } } @@ -537,6 +629,12 @@ SUITE(span_tests) CHECK(s.length() == 1 && s.data() == ptr.get()); CHECK(s[0] == 4); } + + { + auto s = make_span(ptr); + CHECK(s.length() == 1 && s.data() == ptr.get()); + CHECK(s[0] == 4); + } } { @@ -546,6 +644,11 @@ SUITE(span_tests) span s{ptr}; CHECK(s.length() == 0 && s.data() == nullptr); } + + { + auto s = make_span(ptr); + CHECK(s.length() == 0 && s.data() == nullptr); + } } } @@ -631,6 +734,14 @@ SUITE(span_tests) span s{m}; #endif } + + { + auto s = make_span(v); + CHECK(s.size() == narrow_cast(v.size()) && s.data() == v.data()); + + auto cs = make_span(cv); + CHECK(cs.size() == narrow_cast(cv.size()) && cs.data() == cv.data()); + } } TEST(from_convertible_span_constructor)