algorithm_test, span_tests.cpp

This commit is contained in:
Werner Henze 2024-12-30 13:38:45 +01:00 committed by Werner Henze
parent cb03a17b7e
commit 6436dbfda0
2 changed files with 151 additions and 215 deletions

View File

@ -188,7 +188,7 @@ TEST(algorithm_tests, incompatible_type)
span<int> src_span_dyn(src);
span<int, 4> src_span_static(src);
span<int*> dst_span_dyn(dst);
span<int*, 4> dst_span_static(dst);
span<int*, 4> dst_span_static(gsl::make_span(dst));
// every line should produce a compilation error
copy(src_span_dyn, dst_span_dyn);

View File

@ -62,8 +62,7 @@ struct AddressOverloaded
#if (__cplusplus > 201402L)
[[maybe_unused]]
#endif
AddressOverloaded
operator&() const
AddressOverloaded operator&() const
{
return {};
}
@ -298,70 +297,14 @@ TEST(span_test, from_array_constructor)
int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<int, 6> s{arr};
}
{
span<int, 0> s{arr};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == &arr[0]);
}
{
span<int> s{arr2d};
EXPECT_TRUE(s.size() == 6);
EXPECT_TRUE(s.data() == &arr2d[0][0]);
EXPECT_TRUE(s[0] == 1);
EXPECT_TRUE(s[5] == 6);
}
{
span<int, 0> s{arr2d};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == &arr2d[0][0]);
}
{
span<int, 6> s{arr2d};
}
#endif
{
const span<int[3]> s{std::addressof(arr2d[0]), 1};
EXPECT_TRUE(s.size() == 1);
EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
}
int arr3d[2][3][2] = { { {1, 2}, {3, 4}, {5, 6} }, { {7, 8}, {9, 10}, {11, 12} } };
int arr3d[2][3][2] = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}};
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<int> s{arr3d};
EXPECT_TRUE(s.size() == 12);
EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
EXPECT_TRUE(s[0] == 1);
EXPECT_TRUE(s[11] == 12);
}
{
span<int, 0> s{arr3d};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
}
{
span<int, 11> s{arr3d};
}
{
span<int, 12> s{arr3d};
EXPECT_TRUE(s.size() == 12);
EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
EXPECT_TRUE(s[0] == 1);
EXPECT_TRUE(s[5] == 6);
}
#endif
{
const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
EXPECT_TRUE(s.size() == 1);
@ -428,42 +371,9 @@ TEST(span_test, from_std_array_constructor)
EXPECT_TRUE(ao_arr.data() == fs.data());
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<int, 2> s{arr};
EXPECT_TRUE(s.size() == 2);
EXPECT_TRUE(s.data() == arr.data());
span<const int, 2> cs{arr};
EXPECT_TRUE(cs.size() == 2);
EXPECT_TRUE(cs.data() == arr.data());
}
{
span<int, 0> s{arr};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == arr.data());
span<const int, 0> cs{arr};
EXPECT_TRUE(cs.size() == 0);
EXPECT_TRUE(cs.data() == arr.data());
}
{
span<int, 5> s{arr};
}
{
auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
auto take_a_span = [](span<int> s) { static_cast<void>(s); };
// try to take a temporary std::array
take_a_span(get_an_array());
}
#endif
{
auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
auto take_a_span = [](span<const int>) {};
// try to take a temporary std::array
take_a_span(get_an_array());
}
@ -493,24 +403,6 @@ TEST(span_test, from_const_std_array_constructor)
EXPECT_TRUE(s.data() == ao_arr.data());
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<const int, 2> s{arr};
EXPECT_TRUE(s.size() == 2);
EXPECT_TRUE(s.data() == arr.data());
}
{
span<const int, 0> s{arr};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == arr.data());
}
{
span<const int, 5> s{arr};
}
#endif
{
auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
@ -534,28 +426,6 @@ TEST(span_test, from_std_array_const_constructor)
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<const int, 2> s{arr};
EXPECT_TRUE(s.size() == 2);
EXPECT_TRUE(s.data() == arr.data());
}
{
span<const int, 0> s{arr};
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == arr.data());
}
{
span<const int, 5> s{arr};
}
{
span<int, 4> s{arr};
}
#endif
}
TEST(span_test, from_container_constructor)
@ -577,73 +447,40 @@ TEST(span_test, from_container_constructor)
const std::string cstr = "hello";
{
#ifdef CONFIRM_COMPILATION_ERRORS
#ifdef FAIL_ON_SOME_PLATFORMS
span<char> s{str};
EXPECT_TRUE(s.size() == str.size());
EXPECT_TRUE(s.data() == str.data()));
EXPECT_TRUE(s.data() == str.data());
#endif
span<const char> cs{str};
EXPECT_TRUE(cs.size() == str.size());
EXPECT_TRUE(cs.data() == str.data());
span<const char> cs{str};
EXPECT_TRUE(cs.size() == str.size());
EXPECT_TRUE(cs.data() == str.data());
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
span<char> s{cstr};
#endif
span<const char> cs{cstr};
EXPECT_TRUE(cs.size() == cstr.size());
EXPECT_TRUE(cs.data() == cstr.data());
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
auto get_temp_vector = []() -> std::vector<int> { return {}; };
auto use_span = [](span<int> s) { static_cast<void>(s); };
use_span(get_temp_vector());
#endif
}
{
auto get_temp_vector = []() -> std::vector<int> { return {}; };
auto use_span = [](span<const int> s) { static_cast<void>(s); };
use_span(get_temp_vector());
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
auto get_temp_string = []() -> std::string { return {}; };
auto use_span = [](span<char> s) { static_cast<void>(s); };
use_span(get_temp_string());
#endif
}
{
auto get_temp_string = []() -> std::string { return {}; };
auto use_span = [](span<const char> s) { static_cast<void>(s); };
use_span(get_temp_string());
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
auto get_temp_vector = []() -> const std::vector<int> { return {}; };
auto use_span = [](span<const char> s) { static_cast<void>(s); };
use_span(get_temp_vector());
#endif
}
{
auto get_temp_string = []() -> const std::string { return {}; };
auto use_span = [](span<const char> s) { static_cast<void>(s); };
use_span(get_temp_string());
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
std::map<int, int> m;
span<int> s{m};
#endif
}
}
TEST(span_test, from_convertible_span_constructor)
@ -799,7 +636,7 @@ TEST(span_test, first)
{
span<int, 5> av = arr;
#ifdef CONFIRM_COMPILATION_ERRORS
#ifdef FAIL_ON_SOME_PLATFORMS
EXPECT_TRUE(av.first<6>().size() == 6);
EXPECT_TRUE(av.first<-1>().size() == -1);
#endif
@ -843,7 +680,7 @@ TEST(span_test, last)
{
span<int, 5> av = arr;
#ifdef CONFIRM_COMPILATION_ERRORS
#ifdef FAIL_ON_SOME_PLATFORMS
EXPECT_TRUE(av.last<6>().size() == 6);
#endif
EXPECT_DEATH(av.last(6).size(), expected);
@ -1147,17 +984,6 @@ TEST(span_test, as_writable_bytes)
{
int a[] = {1, 2, 3, 4};
{
#ifdef CONFIRM_COMPILATION_ERRORS
// you should not be able to get writeable bytes for const objects
span<const int> s = a;
EXPECT_TRUE(s.size() == 4);
span<const byte> bs = as_writable_bytes(s);
EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
EXPECT_TRUE(bs.size() == s.size_bytes());
#endif
}
{
span<int> s;
const auto bs = as_writable_bytes(s);
@ -1197,8 +1023,8 @@ TEST(span_test, fixed_size_conversions)
static_cast<void>(s);
}
// initialization or assignment to static span that REDUCES size is NOT ok
#ifdef CONFIRM_COMPILATION_ERRORS
// initialization or assignment to static span that REDUCES size is NOT ok
{
span<int, 2> s = arr;
}
@ -1206,11 +1032,9 @@ TEST(span_test, fixed_size_conversions)
span<int, 2> s2 = s4;
static_cast<void>(s2);
}
#endif
// even when done dynamically
{
/*
// this now results in a compile-time error, rather than runtime.
// There is no suitable conversion from dynamic span to fixed span.
span<int> s = arr;
@ -1219,8 +1043,8 @@ TEST(span_test, fixed_size_conversions)
static_cast<void>(s2);
};
EXPECT_DEATH(f(), expected);
*/
}
#endif
// but doing so explicitly is ok
@ -1234,19 +1058,19 @@ TEST(span_test, fixed_size_conversions)
static_cast<void>(s1);
}
/*
// this is not a legal operation in std::span, so we are no longer supporting it
// conversion from span<int, 4> to span<int, dynamic_extent> via call to `first`
// then convert from span<int, dynamic_extent> to span<int, 1>
// The dynamic to fixed extents are not supported in the standard
// to make this work, span<int, 1> would need to be span<int>.
{
#ifdef CONFIRM_COMPILATION_ERRORS
// this is not a legal operation in std::span, so we are no longer supporting it
// conversion from span<int, 4> to span<int, dynamic_extent> via call to `first`
// then convert from span<int, dynamic_extent> to span<int, 1>
// The dynamic to fixed extents are not supported in the standard
// to make this work, span<int, 1> would need to be span<int>.
{
// NB: implicit conversion to span<int,1> from span<int>
span<int, 1> s1 = s4.first(1);
static_cast<void>(s1);
}
*/
// NB: implicit conversion to span<int,1> from span<int>
span<int, 1> s1 = s4.first(1);
static_cast<void>(s1);
}
#endif
// initialization or assignment to static span that requires size INCREASE is not ok.
int arr2[2] = {1, 2};
@ -1268,16 +1092,17 @@ TEST(span_test, fixed_size_conversions)
EXPECT_DEATH(f(), expected);
}
/*
// This no longer compiles. There is no suitable conversion from dynamic span to a fixed size
span.
// this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
span<int> av = arr2; auto f = [&]() {
const span<int, 4> _s4 = av;
static_cast<void>(_s4);
};
EXPECT_DEATH(f(), expected);
*/
#ifdef CONFIRM_COMPILATION_ERRORS
// This no longer compiles. There is no suitable conversion from dynamic span to a fixed size
// span. this should fail - we are trying to assign a small dynamic span to a fixed_size larger
// one
span<int> av = arr2;
auto f = [&]() {
const span<int, 4> _s4 = av;
static_cast<void>(_s4);
};
EXPECT_DEATH(f(), expected);
#endif
}
TEST(span_test, interop_with_std_regex)
@ -1376,8 +1201,119 @@ TEST(span_test, msvc_compile_error_PR1100)
int arr[]{1, 7, 2, 9};
gsl::span sp{arr, std::size(arr)};
std::ranges::sort(sp);
for (const auto& e : sp) {
(void)e;
}
for (const auto& e : sp) { (void) e; }
}
#endif // defined(__cpp_lib_span) && defined(__cpp_lib_ranges)
#if __cplusplus >= 201703l
using std::void_t;
#else // __cplusplus >= 201703l
template <class...>
using void_t = void;
#endif // __cplusplus < 201703l
template <typename U, typename V, typename = void>
static constexpr bool CtorCompilesFor = false;
template <typename U, typename V>
static constexpr bool CtorCompilesFor<U, V, void_t<decltype(U{std::declval<V>()})>> = true;
static_assert(CtorCompilesFor<span<int>, std::array<int, 12>&>,
"CtorCompilesFor<span<int>, std::array<int, 12>&>");
static_assert(CtorCompilesFor<span<int, 4>, std::array<int, 4>&>,
"CtorCompilesFor<span<int, 4>, std::array<int, 4>&>");
static_assert(CtorCompilesFor<span<int*>, std::array<int*, 12>&>,
"CtorCompilesFor<span<int*>, std::array<int*, 12>&>");
static_assert(!CtorCompilesFor<span<int*, 4>, std::array<int*, 12>&>,
"!CtorCompilesFor<span<int*, 4>, std::array<int*, 12>&>");
static_assert(CtorCompilesFor<span<int, 6>, std::array<int, 6>&>,
"CtorCompilesFor<span<int, 6>, std::array<int, 6>&>");
static_assert(!CtorCompilesFor<span<int, 6>, std::array<int, 5>&>,
"!CtorCompilesFor<span<int, 6>, std::array<int, 5>&>");
static_assert(!CtorCompilesFor<span<int, 0>, std::array<int, 5>&>,
"!CtorCompilesFor<span<int, 0>, std::array<int, 5>&>");
static_assert(!CtorCompilesFor<span<int>, int[2][3]>, "!CtorCompilesFor<span<int>, int[2][3]>");
static_assert(!CtorCompilesFor<span<int, 0>, int[2][3]>,
"!CtorCompilesFor<span<int, 0>, int[2][3]>");
static_assert(!CtorCompilesFor<span<int, 6>, int[2][3]>,
"!CtorCompilesFor<span<int, 6>, int[2][3]>");
static_assert(!CtorCompilesFor<span<int>, int[2][3][2]>,
"!CtorCompilesFor<span<int>, int[2][3][2]>");
static_assert(!CtorCompilesFor<span<int, 0>, int[2][3][2]>,
"!CtorCompilesFor<span<int, 0>, int[2][3][2]>");
static_assert(!CtorCompilesFor<span<int, 11>, int[2][3][2]>,
"!CtorCompilesFor<span<int, 11>, int[2][3][2]>");
static_assert(!CtorCompilesFor<span<int, 12>, int[2][3][2]>,
"!CtorCompilesFor<span<int, 12>, int[2][3][2]>");
static_assert(!CtorCompilesFor<span<int, 2>, std::array<int, 4>&>,
"!CtorCompilesFor<span<int, 2>, std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 2>, std::array<int, 4>&>,
"!CtorCompilesFor<span<const int, 2>, std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<int, 0>, std::array<int, 4>&>,
"!CtorCompilesFor<span<int, 0>, std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 0>, std::array<int, 4>&>,
"!CtorCompilesFor<span<const int, 0>, std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<int, 5>, std::array<int, 4>&>,
"!CtorCompilesFor<span<int, 5>, std::array<int, 4>&>");
static_assert(CtorCompilesFor<span<int, 4>, std::array<int, 4>&>,
"CtorCompilesFor<span<int, 4>, std::array<int, 4>&>");
#ifdef FAIL_ON_SOME_PLATFORMS
static_assert(!CtorCompilesFor<span<int, 4>, std::array<int, 4>&&>,
"!CtorCompilesFor<span<int, 4>, std::array<int, 4>&&>");
#endif
static_assert(!CtorCompilesFor<span<const int, 2>, const std::array<int, 4>&>,
"!CtorCompilesFor<span<const int, 2>, const std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 0>, const std::array<int, 4>&>,
"!CtorCompilesFor<span<const int, 0>, const std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 5>, const std::array<int, 4>&>,
"!CtorCompilesFor<span<const int, 5>, const std::array<int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 2>, std::array<const int, 4>&>,
"!CtorCompilesFor<span<const int, 2>, std::array<const int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 0>, std::array<const int, 4>&>,
"!CtorCompilesFor<span<const int, 0>, std::array<const int, 4>&>");
static_assert(!CtorCompilesFor<span<const int, 5>, std::array<const int, 4>&>,
"!CtorCompilesFor<span<const int, 5>, std::array<const int, 4>&>");
static_assert(!CtorCompilesFor<span<int, 4>, std::array<const int, 4>&>,
"!CtorCompilesFor<span<int, 4>, std::array<const int, 4>&>");
static_assert(!CtorCompilesFor<span<char>, const std::string&>,
"!CtorCompilesFor<span<char>, const std::string&>");
static_assert(CtorCompilesFor<span<int>, std::vector<int>&>,
"CtorCompilesFor<span<int>, std::vector<int>&>");
static_assert(CtorCompilesFor<span<const int>, std::vector<int>&&>,
"CtorCompilesFor<span<const int>, std::vector<int>&&>");
#ifdef FAIL_ON_SOME_PLATFORMS
static_assert(!CtorCompilesFor<span<int>, std::vector<int>&&>,
"!CtorCompilesFor<span<int>, std::vector<int>&&>");
static_assert(!CtorCompilesFor<span<int>, const std::vector<int>&&>,
"!CtorCompilesFor<span<int>, const std::vector<int>&&>");
#endif
#ifdef FAIL_ON_SOME_PLATFORMS
static_assert(CtorCompilesFor<span<char>, std::string&>,
"CtorCompilesFor<span<char>, std::string&>");
#endif
static_assert(CtorCompilesFor<span<const char>, std::string&&>,
"CtorCompilesFor<span<const char>, std::string&&>");
static_assert(!CtorCompilesFor<span<char>, std::string&&>,
"!CtorCompilesFor<span<char>, std::string&&>");
static_assert(!CtorCompilesFor<span<char>, const std::string&&>,
"!CtorCompilesFor<span<char>, const std::string&&>");
static_assert(!CtorCompilesFor<span<int>, std::map<int, int>&>,
"!CtorCompilesFor<span<int>, std::map<int, int>&>");
static_assert(CtorCompilesFor<span<int>, span<int, 4>&>,
"CtorCompilesFor<span<int>, span<int, 4>&>");
static_assert(CtorCompilesFor<span<int, 4>, span<int, 4>&>,
"CtorCompilesFor<span<int, 4>, span<int, 4>&>");
static_assert(!CtorCompilesFor<span<int, 2>, span<int, 4>&>,
"!CtorCompilesFor<span<int, 2>, span<int, 4>&>");
template <typename U, typename = void>
static constexpr bool AsWritableBytesCompilesFor = false;
template <typename U>
static constexpr bool
AsWritableBytesCompilesFor<U, void_t<decltype(as_writable_bytes(std::declval<U>()))>> = true;
static_assert(AsWritableBytesCompilesFor<span<int>>,
"AsWriteableBytesCompilesFor<span<int>>");
static_assert(!AsWritableBytesCompilesFor<span<const int>>,
"!AsWriteableBytesCompilesFor<span<const int>>");