mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge branch 'Microsoft/master'
This commit is contained in:
commit
f873dde6e7
@ -12,6 +12,7 @@ matrix:
|
|||||||
packages:
|
packages:
|
||||||
- clang-3.6
|
- clang-3.6
|
||||||
- cmake
|
- cmake
|
||||||
|
- g++-5
|
||||||
sources: &sources
|
sources: &sources
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-precise-3.6
|
- llvm-toolchain-precise-3.6
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# GSL: Guidelines Support Library [![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL)
|
# GSL: Guidelines Support Library [![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL) [![Build status](https://ci.appveyor.com/api/projects/status/github/Microsoft/GSL?svg=true)](https://ci.appveyor.com/project/neilmacintosh/GSL)
|
||||||
|
|
||||||
The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the
|
The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the
|
||||||
[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org).
|
[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org).
|
||||||
|
File diff suppressed because it is too large
Load Diff
200
include/gsl.h
200
include/gsl.h
@ -195,195 +195,21 @@ private:
|
|||||||
not_null<T>& operator-=(size_t) = delete;
|
not_null<T>& operator-=(size_t) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// maybe_null
|
|
||||||
//
|
|
||||||
// Describes an optional pointer - provides symmetry with not_null
|
|
||||||
//
|
|
||||||
template<class T>
|
|
||||||
class maybe_null_ret;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class maybe_null_dbg
|
|
||||||
{
|
|
||||||
template<class U>
|
|
||||||
friend class maybe_null_dbg;
|
|
||||||
|
|
||||||
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
|
|
||||||
public:
|
|
||||||
maybe_null_dbg() : ptr_(nullptr), tested_(false) {}
|
|
||||||
maybe_null_dbg(std::nullptr_t) : ptr_(nullptr), tested_(false) {}
|
|
||||||
|
|
||||||
maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {}
|
|
||||||
maybe_null_dbg& operator=(const T& p)
|
|
||||||
{
|
|
||||||
if (ptr_ != p)
|
|
||||||
{
|
|
||||||
ptr_ = p;
|
|
||||||
tested_ = false;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {}
|
|
||||||
maybe_null_dbg& operator=(const maybe_null_dbg& rhs)
|
|
||||||
{
|
|
||||||
if (this != &rhs)
|
|
||||||
{
|
|
||||||
ptr_ = rhs.ptr_;
|
|
||||||
tested_ = false;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg(const not_null<U> &other) : ptr_(other.get()), tested_(false) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg& operator=(const not_null<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.get();
|
|
||||||
tested_ = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg(const maybe_null_dbg<U> &other) : ptr_(other.ptr_), tested_(false) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg& operator=(const maybe_null_dbg<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.ptr_;
|
|
||||||
tested_ = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg(const maybe_null_ret<U> &other) : ptr_(other.get()), tested_(false) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg& operator=(const maybe_null_ret<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.get();
|
|
||||||
tested_ = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool present() const { tested_ = true; return ptr_ != nullptr; }
|
|
||||||
|
|
||||||
bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; }
|
|
||||||
bool operator!=(const T& rhs) const { return !(*this == rhs); }
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
bool operator==(const maybe_null_dbg<U>& rhs) const { tested_ = true; rhs.tested_ = true; return ptr_ == rhs.ptr_; }
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
bool operator!=(const maybe_null_dbg<U>& rhs) const { return !(*this == rhs); }
|
|
||||||
|
|
||||||
T get() const {
|
|
||||||
fail_fast_assert(tested_);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
__assume(ptr_ != nullptr);
|
|
||||||
#endif
|
|
||||||
return ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T() const { return get(); }
|
|
||||||
T operator->() const { return get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// unwanted operators...pointers only point to single objects!
|
|
||||||
// TODO ensure all arithmetic ops on this type are unavailable
|
|
||||||
maybe_null_dbg<T>& operator++() = delete;
|
|
||||||
maybe_null_dbg<T>& operator--() = delete;
|
|
||||||
maybe_null_dbg<T> operator++(int) = delete;
|
|
||||||
maybe_null_dbg<T> operator--(int) = delete;
|
|
||||||
maybe_null_dbg<T>& operator+(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator+=(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator-(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator-=(size_t) = delete;
|
|
||||||
|
|
||||||
T ptr_;
|
|
||||||
mutable bool tested_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class maybe_null_ret
|
|
||||||
{
|
|
||||||
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
|
|
||||||
public:
|
|
||||||
maybe_null_ret() : ptr_(nullptr) {}
|
|
||||||
maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {}
|
|
||||||
|
|
||||||
maybe_null_ret(const T& p) : ptr_(p) {}
|
|
||||||
maybe_null_ret& operator=(const T& p) { ptr_ = p; return *this; }
|
|
||||||
|
|
||||||
maybe_null_ret(const maybe_null_ret& rhs) = default;
|
|
||||||
maybe_null_ret& operator=(const maybe_null_ret& rhs) = default;
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret(const not_null<U> &other) : ptr_(other.get()) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret& operator=(const not_null<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret(const maybe_null_ret<U> &other) : ptr_(other.get()) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret& operator=(const maybe_null_ret<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret(const maybe_null_dbg<U> &other) : ptr_(other.get()) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret& operator=(const maybe_null_dbg<U> &other)
|
|
||||||
{
|
|
||||||
ptr_ = other.get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool present() const { return ptr_ != nullptr; }
|
|
||||||
|
|
||||||
T get() const { return ptr_; }
|
|
||||||
|
|
||||||
operator T() const { return get(); }
|
|
||||||
T operator->() const { return get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// unwanted operators...pointers only point to single objects!
|
|
||||||
// TODO ensure all arithmetic ops on this type are unavailable
|
|
||||||
maybe_null_ret<T>& operator++() = delete;
|
|
||||||
maybe_null_ret<T>& operator--() = delete;
|
|
||||||
maybe_null_ret<T> operator++(int) = delete;
|
|
||||||
maybe_null_ret<T> operator--(int) = delete;
|
|
||||||
maybe_null_ret<T>& operator+(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator+=(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator-(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator-=(size_t) = delete;
|
|
||||||
|
|
||||||
T ptr_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T> using maybe_null = maybe_null_ret<T>;
|
|
||||||
|
|
||||||
} // namespace gsl
|
} // namespace gsl
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
#undef constexpr
|
#undef constexpr
|
||||||
|
@ -47,7 +47,6 @@ add_gsl_test(array_view_tests)
|
|||||||
add_gsl_test(string_view_tests)
|
add_gsl_test(string_view_tests)
|
||||||
add_gsl_test(at_tests)
|
add_gsl_test(at_tests)
|
||||||
add_gsl_test(bounds_tests)
|
add_gsl_test(bounds_tests)
|
||||||
add_gsl_test(maybenull_tests)
|
|
||||||
add_gsl_test(notnull_tests)
|
add_gsl_test(notnull_tests)
|
||||||
add_gsl_test(assertion_tests)
|
add_gsl_test(assertion_tests)
|
||||||
add_gsl_test(utils_tests)
|
add_gsl_test(utils_tests)
|
||||||
|
@ -16,15 +16,11 @@
|
|||||||
|
|
||||||
#include <UnitTest++/UnitTest++.h>
|
#include <UnitTest++/UnitTest++.h>
|
||||||
#include <array_view.h>
|
#include <array_view.h>
|
||||||
#include <numeric>
|
|
||||||
#include <array>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <functional>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace gsl;
|
using namespace gsl;
|
||||||
@ -554,7 +550,7 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
{
|
{
|
||||||
// zero stride
|
// zero stride
|
||||||
strided_array_view<int, 1> sav{ av, {{4}, {}} };
|
strided_array_view<int, 1> sav{ av,{ { 4 },{} } };
|
||||||
CHECK(sav[0] == 0);
|
CHECK(sav[0] == 0);
|
||||||
CHECK(sav[3] == 0);
|
CHECK(sav[3] == 0);
|
||||||
CHECK_THROW(sav[4], fail_fast);
|
CHECK_THROW(sav[4], fail_fast);
|
||||||
@ -562,7 +558,7 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
{
|
{
|
||||||
// zero extent
|
// zero extent
|
||||||
strided_array_view<int, 1> sav{ av,{ {},{1} } };
|
strided_array_view<int, 1> sav{ av,{ {},{ 1 } } };
|
||||||
CHECK_THROW(sav[0], fail_fast);
|
CHECK_THROW(sav[0], fail_fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,27 +631,17 @@ SUITE(array_view_tests)
|
|||||||
strided_array_view<int, 2> sav5{ av.as_array_view(dim<2>(), dim<2>()), { 1 } };
|
strided_array_view<int, 2> sav5{ av.as_array_view(dim<2>(), dim<2>()), { 1 } };
|
||||||
strided_array_view<int, 2> sav6{ av.as_array_view(dim<2>(), dim<2>()), { 1,1,1 } };
|
strided_array_view<int, 2> sav6{ av.as_array_view(dim<2>(), dim<2>()), { 1,1,1 } };
|
||||||
strided_array_view<int, 2> sav7{ av.as_array_view(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
|
strided_array_view<int, 2> sav7{ av.as_array_view(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
|
||||||
|
|
||||||
|
index<1> index{ 0, 1 };
|
||||||
|
strided_array_view<int, 1> sav8{ arr,{ 1,{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav9{ arr,{ { 1,1 },{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav10{ av,{ 1,{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav11{ av,{ { 1,1 },{ 1,1 } } };
|
||||||
|
strided_array_view<int, 2> sav12{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1 } } };
|
||||||
|
strided_array_view<int, 2> sav13{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } };
|
||||||
|
strided_array_view<int, 2> sav14{ av.as_array_view(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } };
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
|
||||||
// stride initializer list size should match the rank of the array
|
|
||||||
CHECK_THROW((index<1>{ 0,1 }), fail_fast);
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ arr, {1, {1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ arr, {{1,1 }, {1,1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {1, {1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {{1,1 }, {1,1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast);
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(strided_array_view_type_conversion)
|
TEST(strided_array_view_type_conversion)
|
||||||
@ -839,6 +825,94 @@ SUITE(array_view_tests)
|
|||||||
delete[] arr;
|
delete[] arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(index_constructors)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// components of the same type
|
||||||
|
index<3> i1(0, 1, 2);
|
||||||
|
CHECK(i1[0] == 0);
|
||||||
|
|
||||||
|
// components of different types
|
||||||
|
size_t c0 = 0;
|
||||||
|
size_t c1 = 1;
|
||||||
|
index<3> i2(c0, c1, 2);
|
||||||
|
CHECK(i2[0] == 0);
|
||||||
|
|
||||||
|
// from array
|
||||||
|
index<3> i3 = { 0,1,2 };
|
||||||
|
CHECK(i3[0] == 0);
|
||||||
|
|
||||||
|
// from other index of the same size type
|
||||||
|
index<3> i4 = i3;
|
||||||
|
CHECK(i4[0] == 0);
|
||||||
|
|
||||||
|
// from other index of bigger size type
|
||||||
|
index<3, short> i5 = i4;
|
||||||
|
CHECK(i5[0] == 0);
|
||||||
|
|
||||||
|
// from other index of smaller size type
|
||||||
|
index<3, long long> i6 = i4;
|
||||||
|
CHECK(i6[0] == 0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
index<3, long long> i7;
|
||||||
|
CHECK(i7[0] == 0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
index<3, long long> i9 = {};
|
||||||
|
CHECK(i9[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// components of the same type
|
||||||
|
index<1> i1(0);
|
||||||
|
CHECK(i1[0] == 0);
|
||||||
|
|
||||||
|
// components of different types
|
||||||
|
size_t c0 = 0;
|
||||||
|
index<1> i2(c0);
|
||||||
|
CHECK(i2[0] == 0);
|
||||||
|
|
||||||
|
// from array
|
||||||
|
index<1> i3 = { 0 };
|
||||||
|
CHECK(i3[0] == 0);
|
||||||
|
|
||||||
|
// from int
|
||||||
|
index<1> i4 = 0;
|
||||||
|
CHECK(i4[0] == 0);
|
||||||
|
|
||||||
|
// from other index of the same size type
|
||||||
|
index<1> i5 = i3;
|
||||||
|
CHECK(i5[0] == 0);
|
||||||
|
|
||||||
|
// from other index of bigger size type
|
||||||
|
index<1, short> i6 = i5;
|
||||||
|
CHECK(i6[0] == 0);
|
||||||
|
|
||||||
|
// from other index of smaller size type
|
||||||
|
index<1, long long> i7 = i6;
|
||||||
|
CHECK(i7[0] == 0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
index<1, long long> i8;
|
||||||
|
CHECK(i8[0] == 0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
index<1, long long> i9 = {};
|
||||||
|
CHECK(i9[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||||
|
{
|
||||||
|
index<3> i1(0, 1);
|
||||||
|
index<3> i2(0, 1, 2, 3);
|
||||||
|
index<3> i3 = { 0 };
|
||||||
|
index<3> i4 = { 0, 1, 2, 3 };
|
||||||
|
index<1> i5 = { 0,1 };
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
TEST(index_operations)
|
TEST(index_operations)
|
||||||
{
|
{
|
||||||
size_t a[3] = { 0, 1, 2 };
|
size_t a[3] = { 0, 1, 2 };
|
||||||
@ -873,7 +947,18 @@ SUITE(array_view_tests)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
index<2> k = index<2>::shift_left(i);
|
index<3> k = 3 * i;
|
||||||
|
|
||||||
|
CHECK(i[0] == 0);
|
||||||
|
CHECK(i[1] == 1);
|
||||||
|
CHECK(i[2] == 2);
|
||||||
|
CHECK(k[0] == 0);
|
||||||
|
CHECK(k[1] == 3);
|
||||||
|
CHECK(k[2] == 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
index<2> k = details::shift_left(i);
|
||||||
|
|
||||||
CHECK(i[0] == 0);
|
CHECK(i[0] == 0);
|
||||||
CHECK(i[1] == 1);
|
CHECK(i[1] == 1);
|
||||||
@ -914,11 +999,35 @@ SUITE(array_view_tests)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t check_sum = 0;
|
||||||
for (auto num : section)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
CHECK(num == av[idx][1]);
|
check_sum += av[i][1];
|
||||||
idx++;
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t idx = 0;
|
||||||
|
size_t sum = 0;
|
||||||
|
for (auto num : section)
|
||||||
|
{
|
||||||
|
CHECK(num == av[idx][1]);
|
||||||
|
sum += num;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(sum == check_sum);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t idx = length - 1;
|
||||||
|
size_t sum = 0;
|
||||||
|
for (auto iter = section.rbegin(); iter != section.rend(); ++iter)
|
||||||
|
{
|
||||||
|
CHECK(*iter == av[idx][1]);
|
||||||
|
sum += *iter;
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(sum == check_sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,6 +1277,152 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<size_t Rank, typename T1, typename T2>
|
||||||
|
index<Rank, T2> Convert(index<Rank, T1> index)
|
||||||
|
{
|
||||||
|
return{ index };
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DomainConverters)
|
||||||
|
{
|
||||||
|
// to smaller
|
||||||
|
{
|
||||||
|
index<2, int> int_index{ 0,1 };
|
||||||
|
index<2, short> short_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(short_index[0] == 0);
|
||||||
|
CHECK(short_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to smaller (failure)
|
||||||
|
{
|
||||||
|
index<2, int> big_int_index{ std::numeric_limits<int>::max(), 1 };
|
||||||
|
CHECK_THROW((Convert<2,int, short int>(big_int_index)), fail_fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to same, sign mismatch
|
||||||
|
{
|
||||||
|
index<2, int> int_index{ 0,1 };
|
||||||
|
index<2, unsigned int> uint_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(uint_index[0] == 0);
|
||||||
|
CHECK(uint_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to same, sign mismatch, reversed
|
||||||
|
{
|
||||||
|
index<2, unsigned int> uint_index{ 0,1 };
|
||||||
|
index<2, int> int_index{ uint_index };
|
||||||
|
|
||||||
|
CHECK(int_index[0] == 0);
|
||||||
|
CHECK(int_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to smaller, sign mismatch
|
||||||
|
{
|
||||||
|
index<2, int> int_index{ 0,1 };
|
||||||
|
index<2, unsigned short> ushort_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(ushort_index[0] == 0);
|
||||||
|
CHECK(ushort_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger
|
||||||
|
{
|
||||||
|
index<2, int> int_index{ 0,1 };
|
||||||
|
index<2, long long> longlong_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == 0);
|
||||||
|
CHECK(longlong_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger with max index
|
||||||
|
{
|
||||||
|
index<2, int> big_int_index{ std::numeric_limits<int>::max(), 1 };
|
||||||
|
index<2, long long> longlong_index{ big_int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == std::numeric_limits<int>::max());
|
||||||
|
CHECK(longlong_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger, sign mismatch
|
||||||
|
{
|
||||||
|
index<2, int> int_index{ 0,1 };
|
||||||
|
index<2, unsigned long long> ulonglong_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(ulonglong_index[0] == 0);
|
||||||
|
CHECK(ulonglong_index[1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DomainConvertersRank1)
|
||||||
|
{
|
||||||
|
// to smaller
|
||||||
|
{
|
||||||
|
index<1, int> int_index{ 0 };
|
||||||
|
index<1, short> short_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(short_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to smaller (failure)
|
||||||
|
{
|
||||||
|
index<1, int> big_int_index{ std::numeric_limits<int>::max() };
|
||||||
|
|
||||||
|
CHECK_THROW((Convert<1, int, short int>(big_int_index)), fail_fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to same, sign mismatch
|
||||||
|
{
|
||||||
|
index<1, int> int_index{ 0 };
|
||||||
|
index<1, unsigned int> uint_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(uint_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to same, sign mismatch, reversed
|
||||||
|
{
|
||||||
|
index<1, unsigned int> uint_index{ 0 };
|
||||||
|
index<1, int> int_index{ uint_index };
|
||||||
|
|
||||||
|
CHECK(int_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to smaller, sign mismatch
|
||||||
|
{
|
||||||
|
index<1, int> int_index{ 0 };
|
||||||
|
index<1, unsigned short> ushort_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(ushort_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger
|
||||||
|
{
|
||||||
|
index<1, int> int_index{ 0 };
|
||||||
|
index<1, long long> longlong_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger with max index
|
||||||
|
{
|
||||||
|
index<1, int> big_int_index{ std::numeric_limits<int>::max() };
|
||||||
|
index<1, long long> longlong_index{ big_int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == std::numeric_limits<int>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
// to bigger, sign mismatch
|
||||||
|
{
|
||||||
|
index<1, int> int_index{ 0 };
|
||||||
|
index<1, unsigned long long> ulonglong_index{ int_index };
|
||||||
|
|
||||||
|
CHECK(ulonglong_index[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
TEST(constructors)
|
TEST(constructors)
|
||||||
{
|
{
|
||||||
array_view<int, dynamic_range> av(nullptr);
|
array_view<int, dynamic_range> av(nullptr);
|
||||||
@ -1557,7 +1812,36 @@ SUITE(array_view_tests)
|
|||||||
CHECK(wav.data() == (byte*)&a[0]);
|
CHECK(wav.data() == (byte*)&a[0]);
|
||||||
CHECK(wav.length() == sizeof(a));
|
CHECK(wav.length() == sizeof(a));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NonConstIterator)
|
||||||
|
{
|
||||||
|
int a[] = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
|
{
|
||||||
|
array_view<int, dynamic_range> av = a;
|
||||||
|
auto wav = av.as_writeable_bytes();
|
||||||
|
for (auto& b : wav)
|
||||||
|
{
|
||||||
|
b = byte(0);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
CHECK(a[i] == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
array_view<int, dynamic_range> av = a;
|
||||||
|
for (auto& n : av)
|
||||||
|
{
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
CHECK(a[i] == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ArrayViewComparison)
|
TEST(ArrayViewComparison)
|
||||||
|
@ -1,304 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// 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.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace gsl;
|
|
||||||
|
|
||||||
struct MyBase { bool foo() { return true; } };
|
|
||||||
struct MyDerived : public MyBase {};
|
|
||||||
struct Unrelated {};
|
|
||||||
|
|
||||||
SUITE(MaybeNullTests)
|
|
||||||
{
|
|
||||||
TEST(TestMaybeNull1)
|
|
||||||
{
|
|
||||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
|
||||||
// Forbid non-nullptr assignable types
|
|
||||||
maybe_null_ret<std::vector<int>> f_ret(std::vector<int>{1});
|
|
||||||
maybe_null_ret<std::vector<int>> f_ret(std::vector<int>{1});
|
|
||||||
maybe_null_ret<int> z_ret(10);
|
|
||||||
maybe_null_dbg<std::vector<int>> y_dbg({1,2});
|
|
||||||
maybe_null_dbg<int> z_dbg(10);
|
|
||||||
maybe_null_dbg<std::vector<int>> y_dbg({1,2});
|
|
||||||
#endif
|
|
||||||
int n = 5;
|
|
||||||
maybe_null_dbg<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
bool threw = false;
|
|
||||||
|
|
||||||
CHECK_THROW(result = *opt_n, fail_fast);
|
|
||||||
|
|
||||||
maybe_null_ret<std::shared_ptr<int>> x_ret(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
|
|
||||||
maybe_null_dbg<std::shared_ptr<int>> x_dbg(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull2)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
if (opt_n.present())
|
|
||||||
result = *opt_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull3)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
if (opt_n != nullptr)
|
|
||||||
result = *opt_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test4_helper(maybe_null<int *> p)
|
|
||||||
{
|
|
||||||
if (p != nullptr)
|
|
||||||
return *p;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull4)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
int result = 0;
|
|
||||||
result = test4_helper(&n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int test5_helper(maybe_null_dbg<int *> p)
|
|
||||||
{
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull5)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
int result = 0;
|
|
||||||
bool threw = false;
|
|
||||||
|
|
||||||
CHECK_THROW(result = test5_helper(&n), fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
|
||||||
int TestMaybeNull6()
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
maybe_null<int> o(n);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int g_int;
|
|
||||||
void test7_helper(maybe_null<maybe_null<int *> *> outptr)
|
|
||||||
{
|
|
||||||
g_int = 5;
|
|
||||||
|
|
||||||
if (outptr.present())
|
|
||||||
*outptr = &g_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test7b_helper(maybe_null_dbg<maybe_null_dbg<int *> *> outptr)
|
|
||||||
{
|
|
||||||
g_int = 5;
|
|
||||||
|
|
||||||
if (outptr.present())
|
|
||||||
*outptr = &g_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull7a)
|
|
||||||
{
|
|
||||||
maybe_null<int *> outval;
|
|
||||||
test7_helper(&outval);
|
|
||||||
CHECK(outval.present() && *outval == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull7b)
|
|
||||||
{
|
|
||||||
maybe_null_dbg<int *> outval;
|
|
||||||
test7b_helper(&outval);
|
|
||||||
CHECK_THROW((void)*outval, fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
int test8_helper1(maybe_null_dbg<int *> opt)
|
|
||||||
{
|
|
||||||
return *opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test8_helper2a(maybe_null_dbg<int *> opt)
|
|
||||||
{
|
|
||||||
if (!opt.present())
|
|
||||||
return 0;
|
|
||||||
return test8_helper1(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull8a)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null_dbg<int *> opt(&n);
|
|
||||||
CHECK_THROW(test8_helper2a(opt), fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONVERT_TO_PTR_TO_CONST
|
|
||||||
int test9_helper(maybe_null<const int *> copt)
|
|
||||||
{
|
|
||||||
if (copt.present())
|
|
||||||
return *copt;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMaybeNull9()
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt(&n);
|
|
||||||
CHECK_THROW(test9_helper(opt), fail_fast);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(TestMaybeNullCasting)
|
|
||||||
{
|
|
||||||
MyDerived derived;
|
|
||||||
maybe_null<MyDerived*> p = &derived;
|
|
||||||
CHECK(p.present());
|
|
||||||
|
|
||||||
maybe_null<MyBase*> q = p;
|
|
||||||
CHECK(q == p);
|
|
||||||
|
|
||||||
maybe_null_dbg<MyDerived*> pdbg = &derived;
|
|
||||||
CHECK(pdbg.present());
|
|
||||||
|
|
||||||
maybe_null_dbg<MyBase*> qdbg = pdbg;
|
|
||||||
CHECK(qdbg == pdbg);
|
|
||||||
|
|
||||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
|
||||||
maybe_null<Unrelated*> r = p;
|
|
||||||
maybe_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
|
|
||||||
#endif
|
|
||||||
maybe_null_dbg<Unrelated*> t = reinterpret_cast<Unrelated*>(p.get());
|
|
||||||
|
|
||||||
CHECK_THROW((void)(void*)t.get(), fail_fast);
|
|
||||||
maybe_null_dbg<Unrelated*> u = reinterpret_cast<Unrelated*>(p.get());
|
|
||||||
CHECK(u.present());
|
|
||||||
CHECK((void*)p.get() == (void*)u.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNullArrow)
|
|
||||||
{
|
|
||||||
MyDerived derived;
|
|
||||||
maybe_null_dbg<MyDerived*> p = &derived;
|
|
||||||
|
|
||||||
CHECK_THROW(p->foo(), fail_fast);
|
|
||||||
CHECK(p.present());
|
|
||||||
CHECK(p->foo());
|
|
||||||
|
|
||||||
maybe_null<MyBase*> q = p;
|
|
||||||
CHECK(q.present());
|
|
||||||
CHECK(q->foo());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNullCompare)
|
|
||||||
{
|
|
||||||
int i1 = 1;
|
|
||||||
int i2 = 2;
|
|
||||||
|
|
||||||
maybe_null_dbg<int*> p1 = &i1;
|
|
||||||
maybe_null_dbg<int*> p1_2 = &i1;
|
|
||||||
maybe_null_dbg<int*> p2 = &i2;
|
|
||||||
|
|
||||||
CHECK_THROW(p1.get(), fail_fast);
|
|
||||||
CHECK_THROW(p1_2.get(), fail_fast);
|
|
||||||
CHECK_THROW(p2.get(), fail_fast);
|
|
||||||
|
|
||||||
CHECK(p1 != p2);
|
|
||||||
CHECK(!(p1 == p2));
|
|
||||||
CHECK(p1 == p1);
|
|
||||||
CHECK(p1 == p1_2);
|
|
||||||
|
|
||||||
// Make sure we no longer throw here
|
|
||||||
CHECK(p1.get() != nullptr);
|
|
||||||
CHECK(p1_2.get() != nullptr);
|
|
||||||
CHECK(p2.get() != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNullCopy)
|
|
||||||
{
|
|
||||||
int i1 = 1;
|
|
||||||
int i2 = 2;
|
|
||||||
|
|
||||||
maybe_null_dbg<int*> p1 = &i1;
|
|
||||||
maybe_null_dbg<int*> p1_2 = &i1;
|
|
||||||
maybe_null_dbg<int*> p2 = &i2;
|
|
||||||
|
|
||||||
CHECK(p1 != p2);
|
|
||||||
CHECK(p1 == p1_2);
|
|
||||||
|
|
||||||
// Make sure we no longer throw here
|
|
||||||
CHECK(p1.get() != nullptr);
|
|
||||||
CHECK(p2.get() != nullptr);
|
|
||||||
|
|
||||||
p1 = p2;
|
|
||||||
|
|
||||||
// Make sure we now throw
|
|
||||||
CHECK_THROW(p1.get(), fail_fast);
|
|
||||||
|
|
||||||
CHECK(p1 == p2);
|
|
||||||
CHECK(p1 != p1_2);
|
|
||||||
|
|
||||||
// Make sure we no longer throw here
|
|
||||||
CHECK(p1.get() != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNullAssignmentOps)
|
|
||||||
{
|
|
||||||
MyBase base;
|
|
||||||
MyDerived derived;
|
|
||||||
Unrelated unrelated;
|
|
||||||
|
|
||||||
not_null<MyBase*> nnBase(&base);
|
|
||||||
not_null<MyDerived*> nnDerived(&derived);
|
|
||||||
not_null<Unrelated*> nnUnrelated(&unrelated);
|
|
||||||
|
|
||||||
maybe_null_ret<MyBase*> mnBase_ret1(&base), mnBase_ret2;
|
|
||||||
mnBase_ret2 = mnBase_ret1; // maybe_null_ret<T> = maybe_null_ret<T>
|
|
||||||
mnBase_ret2 = nnBase; // maybe_null_ret<T> = not_null<T>
|
|
||||||
|
|
||||||
maybe_null_ret<MyDerived*> mnDerived_ret(&derived);
|
|
||||||
mnBase_ret2 = mnDerived_ret; // maybe_null_ret<T> = maybe_null_ret<U>
|
|
||||||
mnBase_ret1 = &derived; // maybe_null_ret<T> = U;
|
|
||||||
mnBase_ret1 = nnDerived; // maybe_null_ret<T> = not_null<U>
|
|
||||||
|
|
||||||
maybe_null_ret<Unrelated*> mnUnrelated_ret;
|
|
||||||
mnUnrelated_ret = &unrelated; // maybe_null_ret<T> = T
|
|
||||||
|
|
||||||
maybe_null_dbg<MyBase*> mnBase_dbg1(&base), mnBase_dbg2;
|
|
||||||
mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg<T> = maybe_null_dbg<T>
|
|
||||||
mnBase_dbg2 = nnBase; // maybe_null_dbg<T> = not_null<T>
|
|
||||||
|
|
||||||
maybe_null_dbg<MyDerived*> mnDerived_dbg(&derived);
|
|
||||||
mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg<T> = maybe_null_dbg<U>
|
|
||||||
mnBase_dbg1 = &derived; // maybe_null_dbg<T> = U;
|
|
||||||
mnBase_dbg1 = nnDerived; // maybe_null_dbg<T> = not_null<U>
|
|
||||||
|
|
||||||
maybe_null_dbg<Unrelated*> mnUnrelated_dbg;
|
|
||||||
mnUnrelated_dbg = &unrelated; // maybe_null_dbg<T> = T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, const char *[])
|
|
||||||
{
|
|
||||||
return UnitTest::RunAllTests();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user