Updating span<T> to reflect standardization. (PR #309)

Updating span<T> to reflect standardization.
This commit is contained in:
Neil MacIntosh 2016-08-02 15:14:11 -07:00 committed by GitHub
commit 7272552bf9
17 changed files with 5742 additions and 3569 deletions

View File

@ -16,6 +16,6 @@ AllowShortLoopsOnASingleLine: true
PointerAlignment: Left
AlignConsecutiveAssignments: false
AlignTrailingComments: false
AlignTrailingComments: true
SpaceAfterCStyleCast: true

View File

@ -14,6 +14,9 @@ it is simplest to just include [gsl.h](./include/gsl.h) and gain access to the e
> NOTE: We encourage contributions that improve or refine any of the types in this library as well as ports to
other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more information about contributing.
# Project Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
# Quick Start
## Supported Platforms
The test suite that exercises GSL has been built and passes successfully on the following platforms:

View File

@ -21,7 +21,8 @@
#include "gsl_assert.h" // Ensures/Expects
#include "gsl_util.h" // finally()/narrow()/narrow_cast()...
#include "span.h" // span, strided_span...
#include "multi_span.h" // multi_span, strided_span...
#include "span.h" // span
#include "string_span.h" // zstring, string_span, zstring_builder...
#include <memory>
@ -39,13 +40,12 @@
// turn off some misguided warnings
#pragma warning(push)
#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
namespace gsl
{
@ -58,7 +58,6 @@ using std::shared_ptr;
template <class T>
using owner = T;
//
// not_null
//
@ -73,25 +72,31 @@ using owner = T;
// - ensure construction from U* fails with nullptr
// - allow implicit conversion to U*
//
template<class T>
template <class T>
class not_null
{
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public:
not_null(T t) : ptr_(t) { ensure_invariant(); }
not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; }
not_null& operator=(const T& t)
{
ptr_ = t;
ensure_invariant();
return *this;
}
not_null(const not_null &other) = default;
not_null& operator=(const not_null &other) = default;
not_null(const not_null& other) = default;
not_null& operator=(const not_null& other) = default;
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null(const not_null<U> &other)
not_null(const not_null<U>& other)
{
*this = other;
}
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null& operator=(const not_null<U> &other)
not_null& operator=(const not_null<U>& other)
{
ptr_ = other.get();
return *this;
@ -103,7 +108,8 @@ public:
not_null<T>& operator=(std::nullptr_t) = delete;
not_null<T>& operator=(int) = delete;
T get() const {
T get() const
{
#ifdef _MSC_VER
__assume(ptr_ != nullptr);
#endif
@ -118,7 +124,8 @@ public:
private:
T ptr_;
// we assume that the compiler can hoist/prove away most of the checks inlined from this function
// we assume that the compiler can hoist/prove away most of the checks inlined from this
// function
// if not, we could make them optional via conditional compilation
void ensure_invariant() const { Expects(ptr_ != nullptr); }
@ -138,14 +145,11 @@ private:
namespace std
{
template<class T>
struct hash<gsl::not_null<T>>
{
size_t operator()(const gsl::not_null<T> & value) const
{
return hash<T>{}(value);
}
};
template <class T>
struct hash<gsl::not_null<T>>
{
size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
};
} // namespace std

View File

@ -30,15 +30,14 @@
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
//
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ \
defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
//
// GSL.assert: assertions
//
@ -53,18 +52,20 @@ struct fail_fast : public std::runtime_error
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define Expects(cond) if (!(cond)) \
#define Expects(cond) \
if (!(cond)) \
throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
#define Ensures(cond) if (!(cond)) \
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
#define Ensures(cond) \
if (!(cond)) \
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ \
": " GSL_STRINGIFY(__LINE__));
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define Expects(cond) if (!(cond)) std::terminate();
#define Ensures(cond) if (!(cond)) std::terminate();
#define Expects(cond) \
if (!(cond)) std::terminate();
#define Ensures(cond) \
if (!(cond)) std::terminate();
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
@ -73,5 +74,4 @@ struct fail_fast : public std::runtime_error
#endif
#endif // GSL_CONTRACTS_H

125
include/gsl_byte.h Normal file
View File

@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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
#ifdef _MSC_VER
// MSVC 2013 workarounds
#if _MSC_VER <= 1800
// constexpr is not understood
#pragma push_macro("constexpr")
#define constexpr
// noexcept is not understood
#pragma push_macro("noexcept")
#define noexcept
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
namespace gsl
{
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) + static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return {b};
}
} // namespace gsl
#ifdef _MSC_VER
#if _MSC_VER <= 1800
#undef constexpr
#pragma pop_macro("constexpr")
#undef noexcept
#pragma pop_macro("noexcept")
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
#endif // GSL_BYTE_H

View File

@ -21,9 +21,9 @@
#include "gsl_assert.h" // Ensures/Expects
#include <array>
#include <utility>
#include <type_traits>
#include <exception>
#include <type_traits>
#include <utility>
#ifdef _MSC_VER
@ -32,7 +32,7 @@
#define constexpr
#pragma warning(push)
#pragma warning(disable: 4127) // conditional expression is constant
#pragma warning(disable : 4127) // conditional expression is constant
// MSVC 2013 workarounds
#if _MSC_VER <= 1800
@ -42,13 +42,12 @@
// turn off some misguided warnings
#pragma warning(push)
#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
namespace gsl
{
//
@ -60,18 +59,20 @@ template <class F>
class final_act
{
public:
explicit final_act(F f) noexcept
: f_(std::move(f)), invoke_(true)
{}
explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {}
final_act(final_act&& other) noexcept
: f_(std::move(other.f_)), invoke_(other.invoke_)
{ other.invoke_ = false; }
final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
{
other.invoke_ = false;
}
final_act(const final_act&) = delete;
final_act& operator=(const final_act&) = delete;
~final_act() noexcept { if (invoke_) f_(); }
~final_act() noexcept
{
if (invoke_) f_();
}
private:
F f_;
@ -80,34 +81,43 @@ private:
// finally() - convenience function to generate a final_act
template <class F>
inline final_act<F> finally(const F &f)
noexcept { return final_act<F>(f); }
inline final_act<F> finally(const F& f) noexcept
{
return final_act<F>(f);
}
template <class F>
inline final_act<F> finally(F &&f) noexcept
{ return final_act<F>(std::forward<F>(f)); }
inline final_act<F> finally(F&& f) noexcept
{
return final_act<F>(std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template<class T, class U>
template <class T, class U>
inline constexpr T narrow_cast(U u) noexcept
{ return static_cast<T>(u); }
{
return static_cast<T>(u);
}
struct narrowing_error : public std::exception {};
struct narrowing_error : public std::exception
{
};
namespace details
{
template<class T, class U>
struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
{};
template <class T, class U>
struct is_same_signedness
: public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
{
};
}
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template<class T, class U>
template <class T, class U>
inline T narrow(U u)
{
T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u)
throw narrowing_error();
if (static_cast<U>(t) != u) throw narrowing_error();
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
throw narrowing_error();
return t;
@ -117,24 +127,35 @@ inline T narrow(U u)
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector
//
template <class T, size_t N>
constexpr T& at(T(&arr)[N], size_t index)
{ Expects(index < N); return arr[index]; }
constexpr T& at(T (&arr)[N], size_t index)
{
Expects(index < N);
return arr[index];
}
template <class T, size_t N>
constexpr T& at(std::array<T, N>& arr, size_t index)
{ Expects(index < N); return arr[index]; }
{
Expects(index < N);
return arr[index];
}
template <class Cont>
constexpr typename Cont::value_type& at(Cont& cont, size_t index)
{ Expects(index < cont.size()); return cont[index]; }
{
Expects(index < cont.size());
return cont[index];
}
template <class T>
constexpr const T& at(std::initializer_list<T> cont, size_t index)
{ Expects(index < cont.size()); return *(cont.begin() + index); }
{
Expects(index < cont.size());
return *(cont.begin() + index);
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)

2229
include/multi_span.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ else()
endif()
function(add_gsl_test name)
add_executable(${name} ${name}.cpp ../include/gsl.h ../include/gsl_assert.h ../include/gsl_util.h ../include/span.h ../include/string_span.h)
add_executable(${name} ${name}.cpp ../include/gsl.h ../include/gsl_assert.h ../include/gsl_util.h ../include/multi_span.h ../include/span.h ../include/string_span.h)
target_link_libraries(${name} UnitTest++)
install(TARGETS ${name}
RUNTIME DESTINATION bin
@ -45,6 +45,7 @@ function(add_gsl_test name)
endfunction()
add_gsl_test(span_tests)
add_gsl_test(multi_span_tests)
add_gsl_test(strided_span_tests)
add_gsl_test(string_span_tests)
add_gsl_test(at_tests)
@ -53,3 +54,4 @@ add_gsl_test(notnull_tests)
add_gsl_test(assertion_tests)
add_gsl_test(utils_tests)
add_gsl_test(owner_tests)
add_gsl_test(byte_tests)

View File

@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h>
#include <span.h>
#include <multi_span.h>
#include <vector>
using namespace std;
@ -58,7 +58,7 @@ SUITE(bounds_test)
auto itr = bounds.begin();
(void)itr;
#ifdef CONFIRM_COMPILATION_ERRORS
span<int, 4, dynamic_range, 2> av(nullptr, bounds);
multi_span<int, 4, dynamic_range, 2> av(nullptr, bounds);
auto itr2 = av.cbegin();

93
tests/byte_tests.cpp Normal file
View File

@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h>
#include <gsl_byte.h>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
using namespace std;
using namespace gsl;
namespace
{
SUITE(byte_tests)
{
TEST(construction)
{
{
byte b = static_cast<byte>(4);
CHECK(static_cast<unsigned char>(b) == 4);
}
{
byte b = byte(12);
CHECK(static_cast<unsigned char>(b) == 12);
}
// waiting for C++17 enum class direct initializer support
//{
// byte b { 14 };
// CHECK(static_cast<unsigned char>(b) == 14);
//}
}
TEST(bitwise_operations)
{
byte b = byte(0xFF);
byte a = byte(0x00);
CHECK((b | a) == byte(0xFF));
CHECK(a == byte(0x00));
a |= b;
CHECK(a == byte(0xFF));
a = byte(0x01);
CHECK((b & a) == byte(0x01));
a &= b;
CHECK(a == byte(0x01));
CHECK((b ^ a) == byte(0xFE));
CHECK(a == byte(0x01));
a ^= b;
CHECK(a == byte(0xFE));
a = byte(0x01);
CHECK(~a == byte(0xFE));
a = byte(0xFF);
CHECK((a << 4) == byte(0xF0));
CHECK((a >> 4) == byte(0x0F));
a <<= 4;
CHECK(a == byte(0xF0));
a >>= 4;
CHECK(a == byte(0x0F));
}
}
}
int main(int, const char* []) { return UnitTest::RunAllTests(); }

1679
tests/multi_span_tests.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h>
#include <span.h>
#include <multi_span.h>
#include <string>
#include <vector>
@ -39,7 +39,7 @@ SUITE(strided_span_tests)
{
int a[30][4][5];
auto av = as_span(a);
auto av = as_multi_span(a);
auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2});
auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1});
(void)subsub;
@ -49,7 +49,7 @@ SUITE(strided_span_tests)
{
std::vector<int> data(5 * 10);
std::iota(begin(data), end(data), 0);
const span<int, 5, 10> av = as_span(span<int>{data}, dim<5>(), dim<10>());
const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
strided_span<int, 2> av_section_1 = av.section({ 1, 2 }, { 3, 4 });
CHECK((av_section_1[{0, 0}] == 12));
@ -87,13 +87,13 @@ SUITE(strided_span_tests)
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7));
}
// Check span constructor
// Check multi_span constructor
{
int arr[] = { 1, 2 };
// From non-cv-qualified source
{
const span<int> src = arr;
const multi_span<int> src = arr;
strided_span<int, 1> sav{ src, {2, 1} };
CHECK(sav.bounds().index_bounds() == index<1>{ 2 });
@ -102,9 +102,9 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800
//strided_span<const int, 1> sav_c{ {src}, {2, 1} };
strided_span<const int, 1> sav_c{ span<const int>{src}, strided_bounds<1>{2, 1} };
strided_span<const int, 1> sav_c{ multi_span<const int>{src}, strided_bounds<1>{2, 1} };
#else
strided_span<const int, 1> sav_c{ span<const int>{src}, strided_bounds<1>{2, 1} };
strided_span<const int, 1> sav_c{ multi_span<const int>{src}, strided_bounds<1>{2, 1} };
#endif
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 });
CHECK(sav_c.bounds().strides() == index<1>{ 1 });
@ -113,7 +113,7 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800
strided_span<volatile int, 1> sav_v{ src, {2, 1} };
#else
strided_span<volatile int, 1> sav_v{ span<volatile int>{src}, strided_bounds<1>{2, 1} };
strided_span<volatile int, 1> sav_v{ multi_span<volatile int>{src}, strided_bounds<1>{2, 1} };
#endif
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 });
CHECK(sav_v.bounds().strides() == index<1>{ 1 });
@ -122,7 +122,7 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} };
#else
strided_span<const volatile int, 1> sav_cv{ span<const volatile int>{src}, strided_bounds<1>{2, 1} };
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} };
#endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
@ -131,7 +131,7 @@ SUITE(strided_span_tests)
// From const-qualified source
{
const span<const int> src{ arr };
const multi_span<const int> src{ arr };
strided_span<const int, 1> sav_c{ src, {2, 1} };
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 });
@ -141,7 +141,7 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} };
#else
strided_span<const volatile int, 1> sav_cv{ span<const volatile int>{src}, strided_bounds<1>{2, 1} };
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} };
#endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
@ -151,7 +151,7 @@ SUITE(strided_span_tests)
// From volatile-qualified source
{
const span<volatile int> src{ arr };
const multi_span<volatile int> src{ arr };
strided_span<volatile int, 1> sav_v{ src, {2, 1} };
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 });
@ -161,7 +161,7 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} };
#else
strided_span<const volatile int, 1> sav_cv{ span<const volatile int>{src}, strided_bounds<1>{2, 1} };
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} };
#endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
CHECK(sav_cv.bounds().strides() == index<1>{ 1 });
@ -170,7 +170,7 @@ SUITE(strided_span_tests)
// From cv-qualified source
{
const span<const volatile int> src{ arr };
const multi_span<const volatile int> src{ arr };
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} };
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 });
@ -183,11 +183,11 @@ SUITE(strided_span_tests)
{
int arr[2] = { 4, 5 };
const span<int, 2> av(arr, 2);
span<const int, 2> av2{ av };
const multi_span<int, 2> av(arr, 2);
multi_span<const int, 2> av2{ av };
CHECK(av2[1] == 5);
static_assert(std::is_convertible<const span<int, 2>, span<const int, 2>>::value, "ctor is not implicit!");
static_assert(std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value, "ctor is not implicit!");
const strided_span<int, 1> src{ arr, {2, 1} };
strided_span<const int, 1> sav{ src };
@ -258,13 +258,13 @@ SUITE(strided_span_tests)
{
std::vector<int> data(5 * 10);
std::iota(begin(data), end(data), 0);
const span<int, 5, 10> src = as_span(span<int>{data}, dim<5>(), dim<10>());
const multi_span<int, 5, 10> src = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
const strided_span<int, 2> sav{ src, {{5, 10}, {10, 1}} };
#ifdef CONFIRM_COMPILATION_ERRORS
const strided_span<const int, 2> csav{ {src},{ { 5, 10 },{ 10, 1 } } };
#endif
const strided_span<const int, 2> csav{ span<const int, 5, 10>{ src }, { { 5, 10 },{ 10, 1 } } };
const strided_span<const int, 2> csav{ multi_span<const int, 5, 10>{ src }, { { 5, 10 },{ 10, 1 } } };
strided_span<int, 1> sav_sl = sav[2];
CHECK(sav_sl[0] == 20);
@ -317,7 +317,7 @@ SUITE(strided_span_tests)
TEST(strided_span_bounds)
{
int arr[] = { 0, 1, 2, 3 };
span<int> av(arr);
multi_span<int> av(arr);
{
// incorrect sections
@ -413,18 +413,18 @@ SUITE(strided_span_tests)
strided_span<int, 1> sav2{ arr, { 1,1,1 } };
strided_span<int, 1> sav3{ av, { 1 } };
strided_span<int, 1> sav4{ av, { 1,1,1 } };
strided_span<int, 2> sav5{ av.as_span(dim<2>(), dim<2>()), { 1 } };
strided_span<int, 2> sav6{ av.as_span(dim<2>(), dim<2>()), { 1,1,1 } };
strided_span<int, 2> sav7{ av.as_span(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
strided_span<int, 2> sav5{ av.as_multi_span(dim<2>(), dim<2>()), { 1 } };
strided_span<int, 2> sav6{ av.as_multi_span(dim<2>(), dim<2>()), { 1,1,1 } };
strided_span<int, 2> sav7{ av.as_multi_span(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
index<1> index{ 0, 1 };
strided_span<int, 1> sav8{ arr,{ 1,{ 1,1 } } };
strided_span<int, 1> sav9{ arr,{ { 1,1 },{ 1,1 } } };
strided_span<int, 1> sav10{ av,{ 1,{ 1,1 } } };
strided_span<int, 1> sav11{ av,{ { 1,1 },{ 1,1 } } };
strided_span<int, 2> sav12{ av.as_span(dim<2>(), dim<2>()),{ { 1 },{ 1 } } };
strided_span<int, 2> sav13{ av.as_span(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } };
strided_span<int, 2> sav14{ av.as_span(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } };
strided_span<int, 2> sav12{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1 },{ 1 } } };
strided_span<int, 2> sav13{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } };
strided_span<int, 2> sav14{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } };
}
#endif
}
@ -432,7 +432,7 @@ SUITE(strided_span_tests)
TEST(strided_span_type_conversion)
{
int arr[] = { 0, 1, 2, 3 };
span<int> av(arr);
multi_span<int> av(arr);
{
strided_span<int, 1> sav{ av.data(), av.size(), { av.size() / 2, 2 } };
@ -447,7 +447,7 @@ SUITE(strided_span_tests)
#endif
}
span<const byte, dynamic_range> bytes = as_bytes(av);
multi_span<const byte, dynamic_range> bytes = as_bytes(av);
// retype strided array with regular strides - from raw data
{
@ -460,10 +460,10 @@ SUITE(strided_span_tests)
CHECK_THROW(sav3[0][1], fail_fast);
}
// retype strided array with regular strides - from span
// retype strided array with regular strides - from multi_span
{
strided_bounds<2> bounds{ { 2, bytes.size() / 4 }, { bytes.size() / 2, 1 } };
span<const byte, 2, dynamic_range> bytes2 = as_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
strided_span<const byte, 2> sav2{ bytes2, bounds };
strided_span<int, 2> sav3 = sav2.as_strided_span<int>();
CHECK(sav3[0][0] == 0);
@ -475,7 +475,7 @@ SUITE(strided_span_tests)
// retype strided array with not enough elements - last dimension of the array is too small
{
strided_bounds<2> bounds{ { 4,2 },{ 4, 1 } };
span<const byte, 2, dynamic_range> bytes2 = as_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
strided_span<const byte, 2> sav2{ bytes2, bounds };
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
}
@ -483,7 +483,7 @@ SUITE(strided_span_tests)
// retype strided array with not enough elements - strides are too small
{
strided_bounds<2> bounds{ { 4,2 },{ 2, 1 } };
span<const byte, 2, dynamic_range> bytes2 = as_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
strided_span<const byte, 2> sav2{ bytes2, bounds };
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
}
@ -491,7 +491,7 @@ SUITE(strided_span_tests)
// retype strided array with not enough elements - last dimension does not divide by the new typesize
{
strided_bounds<2> bounds{ { 2,6 },{ 4, 1 } };
span<const byte, 2, dynamic_range> bytes2 = as_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
strided_span<const byte, 2> sav2{ bytes2, bounds };
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
}
@ -499,7 +499,7 @@ SUITE(strided_span_tests)
// retype strided array with not enough elements - strides does not divide by the new typesize
{
strided_bounds<2> bounds{ { 2, 1 },{ 6, 1 } };
span<const byte, 2, dynamic_range> bytes2 = as_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim<>(bytes.size() / 2));
strided_span<const byte, 2> sav2{ bytes2, bounds };
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
}
@ -511,7 +511,7 @@ SUITE(strided_span_tests)
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
}
// retype strided array with irregular strides - from span
// retype strided array with irregular strides - from multi_span
{
strided_bounds<1> bounds{ bytes.size() / 2, 2 };
strided_span<const byte, 1> sav2{ bytes, bounds };
@ -522,7 +522,7 @@ SUITE(strided_span_tests)
TEST(empty_strided_spans)
{
{
span<int, 0> empty_av(nullptr);
multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{ empty_av, { 0, 1 } };
CHECK(empty_sav.bounds().index_bounds() == index<1>{ 0 });
@ -553,7 +553,7 @@ SUITE(strided_span_tests)
}
}
void iterate_every_other_element(span<int, dynamic_range> av)
void iterate_every_other_element(multi_span<int, dynamic_range> av)
{
// pick every other element
@ -586,13 +586,13 @@ SUITE(strided_span_tests)
// static bounds
{
span<int, 8> av(arr, 8);
multi_span<int, 8> av(arr, 8);
iterate_every_other_element(av);
}
// dynamic bounds
{
span<int, dynamic_range> av(arr, 8);
multi_span<int, dynamic_range> av(arr, 8);
iterate_every_other_element(av);
}
}
@ -606,13 +606,13 @@ SUITE(strided_span_tests)
arr[2 * i + 1] = i;
}
auto av = as_span(arr, 8);
auto av = as_multi_span(arr, 8);
iterate_every_other_element(av);
delete[] arr;
}
void iterate_second_slice(span<int, dynamic_range, dynamic_range, dynamic_range> av)
void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av)
{
int expected[6] = {2,3,10,11,18,19};
auto section = av.section({0,1,0}, {3,1,2});
@ -653,7 +653,7 @@ SUITE(strided_span_tests)
}
{
span<int, 3, 4, 2> av = arr;
multi_span<int, 3, 4, 2> av = arr;
iterate_second_slice(av);
}
}
@ -670,22 +670,22 @@ SUITE(strided_span_tests)
}
{
auto av = as_span(as_span(arr, 24), dim<3>(), dim<4>(), dim<2>());
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim<4>(), dim<2>());
iterate_second_slice(av);
}
{
auto av = as_span(as_span(arr, 24), dim<>(3), dim<4>(), dim<2>());
auto av = as_multi_span(as_multi_span(arr, 24), dim<>(3), dim<4>(), dim<2>());
iterate_second_slice(av);
}
{
auto av = as_span(as_span(arr, 24), dim<3>(), dim<>(4), dim<2>());
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim<>(4), dim<2>());
iterate_second_slice(av);
}
{
auto av = as_span(as_span(arr, 24), dim<3>(), dim<4>(), dim<>(2));
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim<4>(), dim<>(2));
iterate_second_slice(av);
}
delete[] arr;
@ -693,7 +693,7 @@ SUITE(strided_span_tests)
TEST(strided_span_conversion)
{
// get an span of 'c' values from the list of X's
// get an multi_span of 'c' values from the list of X's
struct X { int a; int b; int c; };
@ -704,7 +704,7 @@ SUITE(strided_span_tests)
auto d1 = sizeof(int) * 12 / d2;
// convert to 4x12 array of bytes
auto av = as_span(as_bytes(as_span(arr, 4)), dim<>(d1), dim<>(d2));
auto av = as_multi_span(as_bytes(as_multi_span(arr, 4)), dim<>(d1), dim<>(d2));
CHECK(av.bounds().index_bounds()[0] == 4);
CHECK(av.bounds().index_bounds()[1] == 12);

View File

@ -40,14 +40,14 @@ SUITE(string_span_tests)
{
std::string s = "Hello there world";
cstring_span<> v = s;
CHECK(v.length() == static_cast<cstring_span<>::size_type>(s.length()));
CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length()));
}
TEST(TestConstructFromStdVector)
{
std::vector<char> vec(5, 'h');
string_span<> v = vec;
CHECK(v.length() == static_cast<string_span<>::size_type>(vec.size()));
string_span<> v {vec};
CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size()));
}
TEST(TestStackArrayConstruction)
@ -109,7 +109,7 @@ SUITE(string_span_tests)
char stack_string[] = "Hello";
cstring_span<> v = ensure_z(stack_string);
auto s2 = gsl::to_string(v);
CHECK(static_cast<cstring_span<>::size_type>(s2.length()) == v.length());
CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length());
CHECK(s2.length() == 5);
}
@ -746,7 +746,7 @@ SUITE(string_span_tests)
T create() { return T{}; }
template <class T>
void use(basic_string_span<T, gsl::dynamic_range> s) {}
void use(basic_string_span<T, gsl::dynamic_extent> s) {}
TEST(MoveConstructors)
{

View File

@ -103,7 +103,7 @@ SUITE(utils_tests)
CHECK(narrow<uint32_t>(int32_t(0)) == 0);
CHECK(narrow<uint32_t>(int32_t(1)) == 1);
CHECK(narrow<uint32_t>(int32_max) == int32_max);
CHECK(narrow<uint32_t>(int32_max) == static_cast<uint32_t>(int32_max));
CHECK_THROW(narrow<uint32_t>(int32_t(-1)), narrowing_error);
CHECK_THROW(narrow<uint32_t>(int32_min), narrowing_error);