mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Updating span<T> to reflect standardization. (PR #309)
Updating span<T> to reflect standardization.
This commit is contained in:
commit
7272552bf9
@ -16,6 +16,6 @@ AllowShortLoopsOnASingleLine: true
|
||||
|
||||
PointerAlignment: Left
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignTrailingComments: false
|
||||
AlignTrailingComments: true
|
||||
|
||||
SpaceAfterCStyleCast: true
|
||||
|
@ -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:
|
||||
|
@ -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>
|
||||
|
||||
@ -45,7 +46,6 @@
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
@ -58,7 +58,6 @@ using std::shared_ptr;
|
||||
template <class T>
|
||||
using owner = T;
|
||||
|
||||
|
||||
//
|
||||
// not_null
|
||||
//
|
||||
@ -77,9 +76,15 @@ 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;
|
||||
@ -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); }
|
||||
|
||||
@ -141,10 +148,7 @@ 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);
|
||||
}
|
||||
size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
@ -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
125
include/gsl_byte.h
Normal 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
|
@ -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
|
||||
|
||||
@ -48,7 +48,6 @@
|
||||
|
||||
#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,25 +81,35 @@ 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)); }
|
||||
{
|
||||
return final_act<F>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||
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>
|
||||
{};
|
||||
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
|
||||
@ -106,8 +117,7 @@ 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;
|
||||
@ -118,23 +128,34 @@ inline T narrow(U u)
|
||||
//
|
||||
template <class T, size_t N>
|
||||
constexpr T& at(T (&arr)[N], size_t index)
|
||||
{ Expects(index < N); return arr[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
2229
include/multi_span.h
Normal file
File diff suppressed because it is too large
Load Diff
2729
include/span.h
2729
include/span.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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)
|
@ -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
93
tests/byte_tests.cpp
Normal 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
1679
tests/multi_span_tests.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1373
tests/span_tests.cpp
1373
tests/span_tests.cpp
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user