mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge branch 'master' into thread_classes
This commit is contained in:
commit
92c2ecba91
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "tests/unittest-cpp"]
|
[submodule "tests/unittest-cpp"]
|
||||||
path = tests/unittest-cpp
|
path = tests/unittest-cpp
|
||||||
url = https://github.com/Microsoft/unittest-cpp.git
|
url = https://github.com/unittest-cpp/unittest-cpp.git
|
||||||
|
@ -118,6 +118,42 @@ std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() == rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() == rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator!=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() != rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() != rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator<(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() < rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() < rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator<=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() <= rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() <= rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator>(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() > rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() > rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
auto operator>=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() >= rhs.get())
|
||||||
|
{
|
||||||
|
return lhs.get() >= rhs.get();
|
||||||
|
}
|
||||||
|
|
||||||
// more unwanted operators
|
// more unwanted operators
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
|
std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
|
||||||
|
@ -133,7 +133,7 @@ namespace details
|
|||||||
using element_type_ = typename Span::element_type;
|
using element_type_ = typename Span::element_type;
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::random_access_iterator_tag;
|
using iterator_category = std::random_access_iterator_tag;
|
||||||
using value_type = std::remove_const_t<element_type_>;
|
using value_type = std::remove_cv_t<element_type_>;
|
||||||
using difference_type = typename Span::index_type;
|
using difference_type = typename Span::index_type;
|
||||||
|
|
||||||
using reference =
|
using reference =
|
||||||
@ -337,6 +337,7 @@ class span
|
|||||||
public:
|
public:
|
||||||
// constants and types
|
// constants and types
|
||||||
using element_type = ElementType;
|
using element_type = ElementType;
|
||||||
|
using value_type = std::remove_cv_t<ElementType>;
|
||||||
using index_type = std::ptrdiff_t;
|
using index_type = std::ptrdiff_t;
|
||||||
using pointer = element_type*;
|
using pointer = element_type*;
|
||||||
using reference = element_type&;
|
using reference = element_type&;
|
||||||
@ -346,6 +347,8 @@ public:
|
|||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
using size_type = index_type;
|
||||||
|
|
||||||
constexpr static const index_type extent = Extent;
|
constexpr static const index_type extent = Extent;
|
||||||
|
|
||||||
// [span.cons], span constructors, copy, assignment, and destructor
|
// [span.cons], span constructors, copy, assignment, and destructor
|
||||||
|
@ -18,15 +18,15 @@ add_definitions(-DGSL_THROW_ON_CONTRACT_VIOLATION)
|
|||||||
if(MSVC) # has the support we need
|
if(MSVC) # has the support we need
|
||||||
# remove unnecessary warnings about unchecked iterators
|
# remove unnecessary warnings about unchecked iterators
|
||||||
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
||||||
add_compile_options(/EHsc /W4)
|
add_compile_options(/EHsc /W4 /WX)
|
||||||
else()
|
else()
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
|
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
|
||||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||||
if(COMPILER_SUPPORTS_CXX14)
|
if(COMPILER_SUPPORTS_CXX14)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fno-strict-aliasing -std=c++14 -O3 -Wall -Wextra -Wpedantic -Wno-missing-braces -Wconversion -Wsign-conversion -Wctor-dtor-privacy -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Woverloaded-virtual")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fno-strict-aliasing -std=c++14 -Wall -Wextra -Wpedantic -Wno-missing-braces -Wconversion -Wsign-conversion -Wctor-dtor-privacy -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Woverloaded-virtual")
|
||||||
elseif(COMPILER_SUPPORTS_CXX11)
|
elseif(COMPILER_SUPPORTS_CXX11)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fno-strict-aliasing -std=c++11 -O3 -Wall -Wextra -Wpedantic -Wno-missing-braces -Wconversion -Wsign-conversion -Wctor-dtor-privacy -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Woverloaded-virtual")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fno-strict-aliasing -std=c++11 -Wall -Wextra -Wpedantic -Wno-missing-braces -Wconversion -Wsign-conversion -Wctor-dtor-privacy -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Woverloaded-virtual")
|
||||||
else()
|
else()
|
||||||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||||
endif()
|
endif()
|
||||||
|
@ -45,8 +45,8 @@ SUITE(at_tests)
|
|||||||
const std::array<int, 4>& c_a = a;
|
const std::array<int, 4>& c_a = a;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
CHECK(&gsl::at(a, i) == &a[i]);
|
CHECK(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
|
||||||
CHECK(&gsl::at(c_a, i) == &a[i]);
|
CHECK(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_THROW(gsl::at(a, -1), fail_fast);
|
CHECK_THROW(gsl::at(a, -1), fail_fast);
|
||||||
@ -61,8 +61,8 @@ SUITE(at_tests)
|
|||||||
const std::vector<int>& c_a = a;
|
const std::vector<int>& c_a = a;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
CHECK(&gsl::at(a, i) == &a[i]);
|
CHECK(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
|
||||||
CHECK(&gsl::at(c_a, i) == &a[i]);
|
CHECK(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_THROW(gsl::at(a, -1), fail_fast);
|
CHECK_THROW(gsl::at(a, -1), fail_fast);
|
||||||
@ -87,7 +87,7 @@ SUITE(at_tests)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || (defined(__clang__) || _MSC_VER >= 1910)
|
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
|
||||||
static constexpr bool test_constexpr()
|
static constexpr bool test_constexpr()
|
||||||
{
|
{
|
||||||
int a1[4] = { 1, 2, 3, 4 };
|
int a1[4] = { 1, 2, 3, 4 };
|
||||||
@ -98,7 +98,9 @@ static constexpr bool test_constexpr()
|
|||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
if (&gsl::at(a1, i) != &a1[i]) return false;
|
if (&gsl::at(a1, i) != &a1[i]) return false;
|
||||||
if (&gsl::at(c_a1, i) != &a1[i]) return false;
|
if (&gsl::at(c_a1, i) != &a1[i]) return false;
|
||||||
if (&gsl::at(c_a2, i) != &c_a2[i]) return false;
|
// requires C++17:
|
||||||
|
// if (&gsl::at(a2, i) != &a2[static_cast<std::size_t>(i)]) return false;
|
||||||
|
if (&gsl::at(c_a2, i) != &c_a2[static_cast<std::size_t>(i)]) return false;
|
||||||
if (gsl::at({1,2,3,4}, i) != i+1) return false;
|
if (gsl::at({1,2,3,4}, i) != i+1) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include <UnitTest++/UnitTest++.h>
|
#include <UnitTest++/UnitTest++.h>
|
||||||
#include <gsl/gsl>
|
#include <gsl/gsl>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
using namespace gsl;
|
using namespace gsl;
|
||||||
|
|
||||||
@ -33,6 +35,54 @@ struct RefCounted
|
|||||||
T* p_;
|
T* p_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// user defined smart pointer with comparison operators returning non bool value
|
||||||
|
template <typename T>
|
||||||
|
struct CustomPtr
|
||||||
|
{
|
||||||
|
CustomPtr(T* p) : p_(p) {}
|
||||||
|
operator T*() { return p_; }
|
||||||
|
bool operator !=(std::nullptr_t)const { return p_ != nullptr; }
|
||||||
|
T* p_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUITE(NotNullTests)
|
SUITE(NotNullTests)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -95,6 +145,101 @@ SUITE(NotNullTests)
|
|||||||
int* q = nullptr;
|
int* q = nullptr;
|
||||||
CHECK_THROW(p = q, fail_fast);
|
CHECK_THROW(p = q, fail_fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestNotNullRawPointerComparison)
|
||||||
|
{
|
||||||
|
int ints[2] = {42, 43};
|
||||||
|
int* p1 = &ints[0];
|
||||||
|
const int* p2 = &ints[1];
|
||||||
|
|
||||||
|
using NotNull1 = not_null<decltype(p1)>;
|
||||||
|
using NotNull2 = not_null<decltype(p2)>;
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) == NotNull1(p1)) == true);
|
||||||
|
CHECK((NotNull1(p1) == NotNull2(p2)) == false);
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) != NotNull1(p1)) == false);
|
||||||
|
CHECK((NotNull1(p1) != NotNull2(p2)) == true);
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) < NotNull1(p1)) == false);
|
||||||
|
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
|
||||||
|
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) > NotNull1(p1)) == false);
|
||||||
|
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
|
||||||
|
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) <= NotNull1(p1)) == true);
|
||||||
|
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
|
||||||
|
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) >= NotNull1(p1)) == true);
|
||||||
|
CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
|
||||||
|
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestNotNullSharedPtrComparison)
|
||||||
|
{
|
||||||
|
auto sp1 = std::make_shared<int>(42);
|
||||||
|
auto sp2 = std::make_shared<const int>(43);
|
||||||
|
|
||||||
|
using NotNullSp1 = not_null<decltype(sp1)>;
|
||||||
|
using NotNullSp2 = not_null<decltype(sp2)>;
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) == NotNullSp1(sp1)) == true);
|
||||||
|
CHECK((NotNullSp1(sp1) == NotNullSp2(sp2)) == false);
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false);
|
||||||
|
CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true);
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) < NotNullSp1(sp1)) == false);
|
||||||
|
CHECK((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2));
|
||||||
|
CHECK((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1));
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) > NotNullSp1(sp1)) == false);
|
||||||
|
CHECK((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2));
|
||||||
|
CHECK((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1));
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true);
|
||||||
|
CHECK((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2));
|
||||||
|
CHECK((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1));
|
||||||
|
|
||||||
|
CHECK((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true);
|
||||||
|
CHECK((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2));
|
||||||
|
CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestNotNullCustomPtrComparison)
|
||||||
|
{
|
||||||
|
int ints[2] = { 42, 43 };
|
||||||
|
CustomPtr<int> p1(&ints[0]);
|
||||||
|
CustomPtr<const int> p2(&ints[1]);
|
||||||
|
|
||||||
|
using NotNull1 = not_null<decltype(p1)>;
|
||||||
|
using NotNull2 = not_null<decltype(p2)>;
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) == NotNull1(p1)) == "true");
|
||||||
|
CHECK((NotNull1(p1) == NotNull2(p2)) == "false");
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) != NotNull1(p1)) == "false");
|
||||||
|
CHECK((NotNull1(p1) != NotNull2(p2)) == "true");
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) < NotNull1(p1)) == "false");
|
||||||
|
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
|
||||||
|
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) > NotNull1(p1)) == "false");
|
||||||
|
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
|
||||||
|
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) <= NotNull1(p1)) == "true");
|
||||||
|
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
|
||||||
|
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
|
||||||
|
|
||||||
|
CHECK((NotNull1(p1) >= NotNull1(p1)) == "true");
|
||||||
|
CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
|
||||||
|
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int, const char *[])
|
int main(int, const char *[])
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit dc6b90838014ab985bf3cd74ac17ad9d00e1fbcb
|
Subproject commit c331bb0deaaf92659a31887c029ee34cac2ab19e
|
Loading…
Reference in New Issue
Block a user