diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 4b8381d8..56b549b8 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -30,6 +30,13 @@ #include "deathTestCommon.h" using namespace gsl; +#if __cplusplus >= 201703l +using std::void_t; +#else // __cplusplus >= 201703l +template +using void_t = void; +#endif // __cplusplus < 201703l + struct MyBase { }; @@ -142,9 +149,38 @@ bool helper_const(not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } } // namespace +template +static constexpr bool CtorCompilesFor_A = false; +template +static constexpr bool + CtorCompilesFor_A{std::declval()})>> = true; + +template +static constexpr bool CtorCompilesFor_B = false; +template +static constexpr bool CtorCompilesFor_B{N})>> = true; + +template +static constexpr bool DefaultCtorCompilesFor = false; +template +static constexpr bool DefaultCtorCompilesFor{})>> = true; + +template +static constexpr bool CtorCompilesFor_C = false; +template +static constexpr bool + CtorCompilesFor_C{std::declval>()})>> = + true; + TEST(notnull_tests, TestNotNullConstructors) { { + static_assert(CtorCompilesFor_A, "CtorCompilesFor_A"); + static_assert(!CtorCompilesFor_A, "!CtorCompilesFor_A"); + static_assert(!CtorCompilesFor_B, "!CtorCompilesFor_B"); + static_assert(!DefaultCtorCompilesFor, "!DefaultCtorCompilesFor"); + static_assert(!CtorCompilesFor_C, "CtorCompilesFor_C"); + #ifdef CONFIRM_COMPILATION_ERRORS // Forbid non-nullptr assignable types not_null> f(std::vector{1}); @@ -271,6 +307,27 @@ TEST(notnull_tests, TestNotNullostream) ostream_helper("string"); } +template +static constexpr bool AssignmentCompilesFor = false; +template +static constexpr bool + AssignmentCompilesFor&>().operator=( + std::declval&>()))>> = true; + +template +static constexpr bool SCastCompilesFor = false; +template +static constexpr bool + SCastCompilesFor(std::declval&>()))>> = + true; + +template +static constexpr bool RCastCompilesFor = false; +template +static constexpr bool RCastCompilesFor< + U, V, void_t(std::declval&>()))>> = true; + TEST(notnull_tests, TestNotNullCasting) { MyBase base; @@ -283,11 +340,30 @@ TEST(notnull_tests, TestNotNullCasting) q = p; // allowed with heterogeneous copy ctor EXPECT_TRUE(q == p); + static_assert(AssignmentCompilesFor, + "AssignmentCompilesFor"); + static_assert(!AssignmentCompilesFor, + "!AssignmentCompilesFor"); + static_assert(!AssignmentCompilesFor, + "!AssignmentCompilesFor"); + static_assert(!AssignmentCompilesFor, + "!AssignmentCompilesFor"); + + static_assert(SCastCompilesFor, "SCastCompilesFor"); + static_assert(SCastCompilesFor, "SCastCompilesFor"); + static_assert(!SCastCompilesFor, "!SCastCompilesFor"); + static_assert(!SCastCompilesFor, + "!SCastCompilesFor"); + static_assert(!RCastCompilesFor, + "!SCastCompilesFor"); + static_assert(!RCastCompilesFor, + "!SCastCompilesFor"); + not_null t(reinterpret_cast(p.get())); EXPECT_TRUE(reinterpret_cast(p.get()) == reinterpret_cast(t.get())); - (void)static_cast(p); - (void)static_cast(p); + (void) static_cast(p); + (void) static_cast(p); } TEST(notnull_tests, TestNotNullAssignment) @@ -429,6 +505,18 @@ TEST(notnull_tests, TestNotNullCustomPtrComparison) #if defined(__cplusplus) && (__cplusplus >= 201703L) +template +static constexpr bool TypeDeductionCtorCompilesFor = false; +template +static constexpr bool + TypeDeductionCtorCompilesFor()})>> = true; + +template +static constexpr bool TypeDeductionHelperCompilesFor = false; +template +static constexpr bool + TypeDeductionHelperCompilesFor()}))>> = true; + TEST(notnull_tests, TestNotNullConstructorTypeDeduction) { { @@ -445,6 +533,9 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction) const int i = 42; not_null x{&i}; + static_assert(TypeDeductionHelperCompilesFor, "TypeDeductionHelperCompilesFor"); + static_assert(!TypeDeductionHelperCompilesFor, + "!TypeDeductionHelperCompilesFor"); helper_const(not_null{&i}); EXPECT_TRUE(*x == 42); @@ -499,6 +590,17 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction) EXPECT_DEATH(helper(not_null{p}), expected); EXPECT_DEATH(helper_const(not_null{p}), expected); } + + static_assert(TypeDeductionCtorCompilesFor, "TypeDeductionCtorCompilesFor"); +#if defined(_MSC_VER) && !defined(__clang__) + // Fails on gcc, clang, xcode, VS clang with + // "error : no type named 'type' in 'std::enable_if'; 'enable_if' cannot be used to + // disable this declaration" + static_assert(!TypeDeductionCtorCompilesFor, + "!TypeDeductionCtorCompilesFor"); + static_assert(!TypeDeductionHelperCompilesFor, + "!TypeDeductionHelperCompilesFor"); +#endif } TEST(notnull_tests, TestVariantEmplace) @@ -513,6 +615,11 @@ TEST(notnull_tests, TestVariantEmplace) } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) +template +static constexpr bool HelperCompilesFor = false; +template +static constexpr bool HelperCompilesFor()))>> = true; + TEST(notnull_tests, TestMakeNotNull) { { @@ -529,6 +636,8 @@ TEST(notnull_tests, TestMakeNotNull) const int i = 42; const auto x = make_not_null(&i); + static_assert(HelperCompilesFor>, + "HelperCompilesFor>"); helper_const(make_not_null(&i)); EXPECT_TRUE(*x == 42); @@ -550,6 +659,8 @@ TEST(notnull_tests, TestMakeNotNull) const int* p = &i; const auto x = make_not_null(p); + static_assert(!HelperCompilesFor>, + "!HelperCompilesFor>"); helper_const(make_not_null(p)); EXPECT_TRUE(*x == 42); @@ -625,79 +736,3 @@ TEST(notnull_tests, TestStdHash) EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr)); } } - -#if __cplusplus >= 201703l -using std::void_t; -#else // __cplusplus >= 201703l -template -using void_t = void; -#endif // __cplusplus < 201703l - -template -static constexpr bool CtorCompilesFor_A = false; -template -static constexpr bool - CtorCompilesFor_A{std::declval()})>> = true; -static_assert(CtorCompilesFor_A, "CtorCompilesFor_A"); -static_assert(!CtorCompilesFor_A, "!CtorCompilesFor_A"); - -template -static constexpr bool CtorCompilesFor_B = false; -template -static constexpr bool CtorCompilesFor_B{N})>> = true; -static_assert(!CtorCompilesFor_B, "!CtorCompilesFor_B"); - -template -static constexpr bool CtorCompilesFor_C = false; -template -static constexpr bool - CtorCompilesFor_C{std::declval>()})>> = - true; -static_assert(!CtorCompilesFor_C, "CtorCompilesFor_C"); - -template -static constexpr bool DefaultCtorCompilesFor = false; -template -static constexpr bool DefaultCtorCompilesFor{})>> = true; -static_assert(!DefaultCtorCompilesFor, "!DefaultCtorCompilesFor"); - -template -static constexpr bool AssignmentCompilesFor = false; -template -static constexpr bool - AssignmentCompilesFor&>().operator=( - std::declval&>()))>> = true; -static_assert(AssignmentCompilesFor, "AssignmentCompilesFor"); -static_assert(!AssignmentCompilesFor, - "!AssignmentCompilesFor"); -static_assert(!AssignmentCompilesFor, - "!AssignmentCompilesFor"); -static_assert(!AssignmentCompilesFor, - "!AssignmentCompilesFor"); - -template -static constexpr bool CastCompilesFor_A = false; -template -static constexpr bool CastCompilesFor_A< - U, V, void_t(std::declval&>()))>> = true; -static_assert(CastCompilesFor_A, "CastCompilesFor_A"); -static_assert(CastCompilesFor_A, "CastCompilesFor_A"); -static_assert(!CastCompilesFor_A, "!CastCompilesFor_A"); -static_assert(!CastCompilesFor_A, "!CastCompilesFor_A"); - -template -static constexpr bool CastCompilesFor_B = false; -template -static constexpr bool CastCompilesFor_B< - U, V, void_t(std::declval&>()))>> = true; -static_assert(!CastCompilesFor_B, "!CastCompilesFor_A"); -static_assert(!CastCompilesFor_B, "!CastCompilesFor_A"); - -template -static constexpr bool HelperCompilesFor = false; -template -static constexpr bool HelperCompilesFor()))>> = true; -static_assert(HelperCompilesFor>, "HelperCompilesFor>"); -static_assert(!HelperCompilesFor>, - "!HelperCompilesFor>"); diff --git a/tests/pointers_tests.cpp b/tests/pointers_tests.cpp index 7757c27a..1c157128 100644 --- a/tests/pointers_tests.cpp +++ b/tests/pointers_tests.cpp @@ -6,6 +6,13 @@ #include #include +#if __cplusplus >= 201703l +using std::void_t; +#else // __cplusplus >= 201703l +template +using void_t = void; +#endif // __cplusplus < 201703l + namespace { // Custom pointer type that can be used for gsl::not_null, but for which these cannot be swapped. @@ -22,6 +29,13 @@ struct NotMoveAssignableCustomPtr int dummy{}; // Without this clang warns, that NotMoveAssignableCustomPtr() is unneeded }; +template +static constexpr bool SwapCompilesFor = false; +template +static constexpr bool + SwapCompilesFor(std::declval&>(), + std::declval&>()))>> = true; + TEST(pointers_test, swap) { // taken from gh-1129: @@ -69,22 +83,9 @@ TEST(pointers_test, swap) EXPECT_TRUE(*a == 1); EXPECT_TRUE(*b == 0); } -} -#if __cplusplus >= 201703l -using std::void_t; -#else // __cplusplus >= 201703l -template -using void_t = void; -#endif // __cplusplus < 201703l - -template -static constexpr bool SwapCompilesFor = false; -template -static constexpr bool - SwapCompilesFor(std::declval&>(), - std::declval&>()))>> = true; -static_assert(!SwapCompilesFor, - "!SwapCompilesFor"); + static_assert(!SwapCompilesFor, + "!SwapCompilesFor"); +} } // namespace diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 627dc62d..5f40a74f 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -48,6 +48,13 @@ using namespace gsl; +#if __cplusplus >= 201703l +using std::void_t; +#else // __cplusplus >= 201703l +template +using void_t = void; +#endif // __cplusplus < 201703l + namespace { @@ -215,13 +222,11 @@ TEST(span_test, from_pointer_length_constructor) TEST(span_test, from_pointer_pointer_construction) { -#if !(defined _MSVC_STL_VERSION) || defined(NDEBUG) - const auto terminateHandler = std::set_terminate([] { - std::cerr << "Expected Death. from_pointer_pointer_construction"; - std::abort(); - }); - const auto expected = GetExpectedDeathString(terminateHandler); -#endif + // const auto terminateHandler = std::set_terminate([] { + // std::cerr << "Expected Death. from_pointer_pointer_construction"; + // std::abort(); + // }); + // const auto expected = GetExpectedDeathString(terminateHandler); int arr[4] = {1, 2, 3, 4}; @@ -252,20 +257,18 @@ TEST(span_test, from_pointer_pointer_construction) EXPECT_TRUE(s.data() == &arr[0]); } -#if !(defined _MSVC_STL_VERSION) || defined(NDEBUG) // this will fail the std::distance() precondition, which asserts on MSVC debug builds - { - auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; - EXPECT_DEATH(workaround_macro(), expected); - } + //{ + // auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} // this will fail the std::distance() precondition, which asserts on MSVC debug builds - { - int* p = nullptr; - auto workaround_macro = [&]() { span s{&arr[0], p}; }; - EXPECT_DEATH(workaround_macro(), expected); - } -#endif + //{ + // int* p = nullptr; + // auto workaround_macro = [&]() { span s{&arr[0], p}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} { int* p = nullptr; @@ -281,20 +284,27 @@ TEST(span_test, from_pointer_pointer_construction) EXPECT_TRUE(s.data() == nullptr); } -#if !(defined _MSVC_STL_VERSION) || defined(NDEBUG) // this will fail the std::distance() precondition, which asserts on MSVC debug builds - { - int* p = nullptr; - auto workaround_macro = [&]() { span s{&arr[0], p}; }; - EXPECT_DEATH(workaround_macro(), expected); - } -#endif + //{ + // int* p = nullptr; + // auto workaround_macro = [&]() { span s{&arr[0], p}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} } +template +static constexpr bool CtorCompilesFor = false; +template +static constexpr bool CtorCompilesFor()})>> = true; + TEST(span_test, from_array_constructor) { int arr[5] = {1, 2, 3, 4, 5}; + static_assert(!CtorCompilesFor, int[5]>, "!CtorCompilesFor, int[5]>"); + static_assert(!CtorCompilesFor, int[5]>, "!CtorCompilesFor, int[5]>"); + static_assert(!CtorCompilesFor, int[2][3]>, "!CtorCompilesFor, int[2][3]>"); + { const span s{arr}; EXPECT_TRUE(s.size() == 5); @@ -309,6 +319,11 @@ TEST(span_test, from_array_constructor) int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; + static_assert(!CtorCompilesFor, int[2][3]>, + "!CtorCompilesFor, int[2][3]>"); + static_assert(!CtorCompilesFor, int[2][3]>, + "!CtorCompilesFor, int[2][3]>"); + { const span s{std::addressof(arr2d[0]), 1}; EXPECT_TRUE(s.size() == 1); @@ -317,6 +332,15 @@ TEST(span_test, from_array_constructor) int arr3d[2][3][2] = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}; + static_assert(!CtorCompilesFor, int[2][3][2]>, + "!CtorCompilesFor, int[2][3][2]>"); + static_assert(!CtorCompilesFor, int[2][3][2]>, + "!CtorCompilesFor, int[2][3][2]>"); + static_assert(!CtorCompilesFor, int[2][3][2]>, + "!CtorCompilesFor, int[2][3][2]>"); + static_assert(!CtorCompilesFor, int[2][3][2]>, + "!CtorCompilesFor, int[2][3][2]>"); + { const span s{std::addressof(arr3d[0]), 1}; EXPECT_TRUE(s.size() == 1); @@ -344,6 +368,13 @@ TEST(span_test, from_dynamic_array_constructor) delete[] arr; } +template +static constexpr bool ConversionCompilesFor = false; +template +static constexpr bool + ConversionCompilesFor()(std::declval()))>> = + true; + TEST(span_test, from_std_array_constructor) { std::array arr = {1, 2, 3, 4}; @@ -383,10 +414,31 @@ TEST(span_test, from_std_array_constructor) EXPECT_TRUE(ao_arr.data() == fs.data()); } + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + +#if !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) + // Fails on "Visual Studio 16 2019/Visual Studio 17 2022, windows-2019/2022, Debug/Release, 14". + static_assert(!ConversionCompilesFor, std::array>, + "!ConversionCompilesFor, std::array>"); +#endif + { auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; auto take_a_span = [](span) {}; // try to take a temporary std::array + static_assert(ConversionCompilesFor, std::array>, + "ConversionCompilesFor, std::array>"); take_a_span(get_an_array()); } } @@ -415,6 +467,13 @@ TEST(span_test, from_const_std_array_constructor) EXPECT_TRUE(s.data() == ao_arr.data()); } + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + static_assert(!CtorCompilesFor, std::array&>, + "!CtorCompilesFor, std::array&>"); + { auto get_an_array = []() -> const std::array { return {1, 2, 3, 4}; }; auto take_a_span = [](span s) { static_cast(s); }; @@ -438,6 +497,15 @@ TEST(span_test, from_std_array_const_constructor) EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } + + static_assert(!CtorCompilesFor, const std::array&>, + "!CtorCompilesFor, const std::array&>"); + static_assert(!CtorCompilesFor, const std::array&>, + "!CtorCompilesFor, const std::array&>"); + static_assert(!CtorCompilesFor, const std::array&>, + "!CtorCompilesFor, const std::array&>"); + static_assert(!CtorCompilesFor, const std::array&>, + "!CtorCompilesFor, const std::array&>"); } TEST(span_test, from_container_constructor) @@ -459,11 +527,8 @@ TEST(span_test, from_container_constructor) const std::string cstr = "hello"; { -#if __cplusplus >= 201703L - span s{str}; - EXPECT_TRUE(s.size() == str.size()); - EXPECT_TRUE(s.data() == str.data()); -#endif + static_assert(CtorCompilesFor, std::string&> == (__cplusplus >= 201703L), + "CtorCompilesFor, std::string&> == (__cplusplus >= 201703L)"); span cs{str}; EXPECT_TRUE(cs.size() == str.size()); @@ -471,28 +536,48 @@ TEST(span_test, from_container_constructor) } { + static_assert(!CtorCompilesFor, const std::string&>, + "!CtorCompilesFor, const std::string&>"); + span cs{cstr}; EXPECT_TRUE(cs.size() == cstr.size()); EXPECT_TRUE(cs.data() == cstr.data()); } +#if !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) + // Fails on "Visual Studio 16 2019/Visual Studio 17 2022, windows-2019/2022, Debug/Release, 14". + static_assert(!ConversionCompilesFor, std::vector>, + "!ConversionCompilesFor, std::vector>"); +#endif // !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) + { auto get_temp_vector = []() -> std::vector { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_vector()); } + static_assert(!ConversionCompilesFor, std::string>, + "!ConversionCompilesFor, std::string>"); + { auto get_temp_string = []() -> std::string { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_string()); } + static_assert(!ConversionCompilesFor, const std::vector>, + "!ConversionCompilesFor, const std::vector>"); + static_assert(!ConversionCompilesFor, const std::string>, + "!ConversionCompilesFor, const std::string>"); + { auto get_temp_string = []() -> const std::string { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_string()); } + + static_assert(!CtorCompilesFor, std::map&>, + "!CtorCompilesFor, std::map&>"); } TEST(span_test, from_convertible_span_constructor) @@ -543,6 +628,21 @@ TEST(span_test, from_convertible_span_constructor) using T = span; EXPECT_DEATH(T{avd}, expected); } + + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); + static_assert(!ConversionCompilesFor, span&>, + "!ConversionCompilesFor, span&>"); } TEST(span_test, copy_move_and_assignment) @@ -911,9 +1011,21 @@ TEST(span_test, rbegin_rend) } } +template +static constexpr bool AsWritableBytesCompilesFor = false; +template +static constexpr bool + AsWritableBytesCompilesFor()))>> = true; + TEST(span_test, as_bytes) { int a[] = {1, 2, 3, 4}; + + static_assert(AsWritableBytesCompilesFor>, "AsWriteableBytesCompilesFor>"); + // you should not be able to get writeable bytes for const objects + static_assert(!AsWritableBytesCompilesFor>, + "!AsWriteableBytesCompilesFor>"); + { const span s = a; EXPECT_TRUE(s.size() == 4); @@ -983,6 +1095,18 @@ TEST(span_test, fixed_size_conversions) static_cast(s); } + // initialization or assignment to static span that REDUCES size is NOT ok + static_assert(!ConversionCompilesFor, int[4]>, + "!ConversionCompilesFor, int[4]>"); + static_assert(!ConversionCompilesFor, span>, + "!ConversionCompilesFor, span>"); + + // even when done dynamically + static_assert(!ConversionCompilesFor, span>, + "!ConversionCompilesFor, span>"); + + // but doing so explicitly is ok + // you can convert statically { const span s2{&arr[0], 2}; @@ -993,9 +1117,24 @@ TEST(span_test, fixed_size_conversions) static_cast(s1); } + // this is not a legal operation in std::span, so we are no longer supporting it + // conversion from span to span via call to `first` + // then convert from span to span + // The dynamic to fixed extents are not supported in the standard + // to make this work, span would need to be span. + static_assert(!ConversionCompilesFor, span>, + "!ConversionCompilesFor, span>"); + // initialization or assignment to static span that requires size INCREASE is not ok. int arr2[2] = {1, 2}; + static_assert(!ConversionCompilesFor, int[2]>, + "!ConversionCompilesFor, int[2]>"); + static_assert(!ConversionCompilesFor, int[2]>, + "!ConversionCompilesFor, int[2]>"); + static_assert(!ConversionCompilesFor, span>, + "!ConversionCompilesFor, span>"); + { auto f = [&]() { const span _s4{arr2, 2}; @@ -1003,6 +1142,12 @@ 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 + static_assert(!ConversionCompilesFor, span>, + "!ConversionCompilesFor, span>"); } TEST(span_test, interop_with_std_regex) @@ -1104,175 +1249,3 @@ TEST(span_test, msvc_compile_error_PR1100) 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 -using void_t = void; -#endif // __cplusplus < 201703l - -template -static constexpr bool CtorCompilesFor = false; -template -static constexpr bool CtorCompilesFor()})>> = true; -static_assert(CtorCompilesFor, std::array&>, - "CtorCompilesFor, std::array&>"); -static_assert(CtorCompilesFor, std::array&>, - "CtorCompilesFor, std::array&>"); -static_assert(CtorCompilesFor, std::array&>, - "CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(CtorCompilesFor, std::array&>, - "CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, int[2][3]>, "!CtorCompilesFor, int[2][3]>"); -static_assert(!CtorCompilesFor, int[2][3]>, - "!CtorCompilesFor, int[2][3]>"); -static_assert(!CtorCompilesFor, int[2][3]>, - "!CtorCompilesFor, int[2][3]>"); -static_assert(!CtorCompilesFor, int[2][3][2]>, - "!CtorCompilesFor, int[2][3][2]>"); -static_assert(!CtorCompilesFor, int[2][3][2]>, - "!CtorCompilesFor, int[2][3][2]>"); -static_assert(!CtorCompilesFor, int[2][3][2]>, - "!CtorCompilesFor, int[2][3][2]>"); -static_assert(!CtorCompilesFor, int[2][3][2]>, - "!CtorCompilesFor, int[2][3][2]>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(CtorCompilesFor, std::array&>, - "CtorCompilesFor, std::array&>"); -#if !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -// Fails on "Visual Studio 16 2019/Visual Studio 17 2022, windows-2019/2022, Debug/Release, 14". -static_assert(!CtorCompilesFor, std::array&&>, - "!CtorCompilesFor, std::array&&>"); -#endif // !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -static_assert(!CtorCompilesFor, const std::array&>, - "!CtorCompilesFor, const std::array&>"); -static_assert(!CtorCompilesFor, const std::array&>, - "!CtorCompilesFor, const std::array&>"); -static_assert(!CtorCompilesFor, const std::array&>, - "!CtorCompilesFor, const std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(!CtorCompilesFor, std::array&>, - "!CtorCompilesFor, std::array&>"); -static_assert(CtorCompilesFor, const std::string&>, - "CtorCompilesFor, const std::string&>"); -static_assert(!CtorCompilesFor, const std::string&>, - "!CtorCompilesFor, const std::string&>"); - -static_assert(CtorCompilesFor, std::vector&>, - "CtorCompilesFor, std::vector&>"); -static_assert(CtorCompilesFor, std::vector&&>, - "CtorCompilesFor, std::vector&&>"); -#if !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -// Fails on "Visual Studio 16 2019/Visual Studio 17 2022, windows-2019/2022, Debug/Release, 14". -static_assert(!CtorCompilesFor, std::vector&&>, - "!CtorCompilesFor, std::vector&&>"); -#endif // !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -static_assert(!CtorCompilesFor, const std::vector&&>, - "!CtorCompilesFor, const std::vector&&>"); - -#if __cplusplus < 201703L -static_assert(!CtorCompilesFor, std::string&>, - "!CtorCompilesFor, std::string&>"); -#endif -static_assert(CtorCompilesFor, std::string&&>, - "CtorCompilesFor, std::string&&>"); -static_assert(!CtorCompilesFor, std::string&&>, - "!CtorCompilesFor, std::string&&>"); -static_assert(!CtorCompilesFor, const std::string&&>, - "!CtorCompilesFor, const std::string&&>"); - -static_assert(!CtorCompilesFor, std::map&>, - "!CtorCompilesFor, std::map&>"); - -static_assert(CtorCompilesFor, span&>, - "CtorCompilesFor, span&>"); -static_assert(CtorCompilesFor, span&>, - "CtorCompilesFor, span&>"); -static_assert(!CtorCompilesFor, span&>, - "!CtorCompilesFor, span&>"); - -template -static constexpr bool ConversionCompilesFor = false; -template -static constexpr bool - ConversionCompilesFor()(std::declval()))>> = - true; -static_assert(ConversionCompilesFor, span>, - "ConversionCompilesFor, span>"); -static_assert(ConversionCompilesFor, span>, - "ConversionCompilesFor, span>"); -static_assert(!ConversionCompilesFor, std::array>, - "!ConversionCompilesFor, std::array>"); -static_assert(!ConversionCompilesFor, std::array>, - "!ConversionCompilesFor, std::array>"); -static_assert(ConversionCompilesFor, std::vector>, - "ConversionCompilesFor, std::vector>"); -#if !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -// Fails on "Visual Studio 16 2019/Visual Studio 17 2022, windows-2019/2022, Debug/Release, 14". -static_assert(!ConversionCompilesFor, std::vector>, - "!ConversionCompilesFor, std::vector>"); -#endif // !defined(_MSC_VER) || (_MSC_VER > 1942) || (__cplusplus >= 201703L) -#if __cplusplus < 201703L -static_assert(!ConversionCompilesFor, std::string>, - "!ConversionCompilesFor, std::string>"); -#endif -static_assert(ConversionCompilesFor, const std::string&>, - "ConversionCompilesFor, const std::string&>"); -static_assert(!ConversionCompilesFor, const std::string&>, - "!ConversionCompilesFor, const std::string&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, span&>, - "!ConversionCompilesFor, span&>"); -static_assert(!ConversionCompilesFor, int[4]>, - "!ConversionCompilesFor, int[4]>"); -static_assert(!ConversionCompilesFor, span>, - "!ConversionCompilesFor, span>"); -static_assert(!ConversionCompilesFor, span>, - "!ConversionCompilesFor, span>"); -static_assert(!ConversionCompilesFor, int[2]>, - "!ConversionCompilesFor, int[2]>"); -static_assert(!ConversionCompilesFor, int[2]>, - "!ConversionCompilesFor, int[2]>"); -static_assert(!ConversionCompilesFor, span>, - "!ConversionCompilesFor, span>"); - -template -static constexpr bool AsWritableBytesCompilesFor = false; -template -static constexpr bool - AsWritableBytesCompilesFor()))>> = true; -static_assert(AsWritableBytesCompilesFor>, "AsWriteableBytesCompilesFor>"); -static_assert(!AsWritableBytesCompilesFor>, - "!AsWriteableBytesCompilesFor>"); diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index 0fbc34ca..d75f5d60 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -23,6 +23,13 @@ using namespace gsl; +#if __cplusplus >= 201703l +using std::void_t; +#else // __cplusplus >= 201703l +template +using void_t = void; +#endif // __cplusplus < 201703l + // stand-in for a user-defined ref-counted class template struct RefCounted @@ -57,9 +64,36 @@ bool strict_helper_const(strict_not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } } // namespace +template +static constexpr bool CtorCompilesFor_A = false; +template +static constexpr bool + CtorCompilesFor_A{std::declval()})>> = true; + +template +static constexpr bool CtorCompilesFor_B = false; +template +static constexpr bool CtorCompilesFor_B{N})>> = true; + +template +static constexpr bool DefaultCtorCompilesFor = false; +template +static constexpr bool DefaultCtorCompilesFor{})>> = true; + +template +static constexpr bool CtorCompilesFor_C = false; +template +static constexpr bool CtorCompilesFor_C< + U, void_t{std::declval>()})>> = true; + TEST(strict_notnull_tests, TestStrictNotNullConstructors) { { + static_assert(CtorCompilesFor_A, "CtorCompilesFor_A"); + static_assert(!CtorCompilesFor_A, "!CtorCompilesFor_A"); + static_assert(!CtorCompilesFor_B, "!CtorCompilesFor_B"); + static_assert(!DefaultCtorCompilesFor, "!DefaultCtorCompilesFor"); + static_assert(!CtorCompilesFor_C, "CtorCompilesFor_C"); #ifdef CONFIRM_COMPILATION_ERRORS // Forbid non-nullptr assignable types strict_not_null> f(std::vector{1}); @@ -155,6 +189,26 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructors) } } +template +static constexpr bool StrictHelperCompilesFor = false; +template +static constexpr bool + StrictHelperCompilesFor()))>> = true; + + +template +static constexpr bool StrictHelperConstCompilesFor = false; +template +static constexpr bool + StrictHelperConstCompilesFor()))>> = + true; + + +template +static constexpr bool HelperCompilesFor = false; +template +static constexpr bool HelperCompilesFor()))>> = true; + TEST(strict_notnull_tests, TestStrictNotNull) { { @@ -164,9 +218,14 @@ TEST(strict_notnull_tests, TestStrictNotNull) #ifdef CONFIRM_COMPILATION_ERRORS strict_not_null snn = &x; #endif + static_assert(!StrictHelperCompilesFor, "!StrictHelperCompilesFor"); + static_assert(!StrictHelperConstCompilesFor, + "!StrictHelperCompilesFor"); const strict_not_null snn1{&x}; + static_assert(StrictHelperCompilesFor>, + "StrictHelperCompilesFor>"); helper(snn1); helper_const(snn1); @@ -180,9 +239,16 @@ TEST(strict_notnull_tests, TestStrictNotNull) #ifdef CONFIRM_COMPILATION_ERRORS strict_not_null snn = &x; #endif + static_assert(!StrictHelperCompilesFor, "!StrictHelperFor"); + static_assert(!StrictHelperConstCompilesFor, + "!StrictHelperCompilesFor"); const strict_not_null snn1{&x}; + static_assert(!HelperCompilesFor>, + "!HelperCompilesFor>"); + static_assert(StrictHelperConstCompilesFor>, + "StrictHelperCompilesFor>"); helper_const(snn1); EXPECT_TRUE(*snn1 == 42); @@ -209,6 +275,8 @@ TEST(strict_notnull_tests, TestStrictNotNull) strict_not_null snn1{&x}; const strict_not_null snn2{&x}; + static_assert(!StrictHelperCompilesFor>, + "!StrictHelperCompilesFor>"); strict_helper_const(snn1); strict_helper_const(snn2); @@ -240,6 +308,8 @@ TEST(strict_notnull_tests, TestStrictNotNull) const not_null nn1 = snn; const not_null nn2{snn}; + static_assert(!HelperCompilesFor>, + "!HelperCompilesFor>"); helper_const(snn); EXPECT_TRUE(snn == nn1); @@ -279,6 +349,8 @@ TEST(strict_notnull_tests, TestStrictNotNull) const strict_not_null snn1{nn}; const strict_not_null snn2{nn}; + static_assert(!StrictHelperCompilesFor>, + "!StrictHelperCompilesFor>"); strict_helper_const(nn); EXPECT_TRUE(snn1 == nn); @@ -318,6 +390,8 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) const int i = 42; strict_not_null x{&i}; + static_assert(!HelperCompilesFor>, + "!HelperCompilesFor>"); helper_const(strict_not_null{&i}); EXPECT_TRUE(*x == 42); @@ -339,6 +413,8 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) const int* p = &i; strict_not_null x{p}; + static_assert(!HelperCompilesFor>, + "!HelperCompilesFor>"); helper_const(strict_not_null{p}); EXPECT_TRUE(*x == 42); @@ -376,73 +452,3 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) #endif } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) - -#if __cplusplus >= 201703l -using std::void_t; -#else // __cplusplus >= 201703l -template -using void_t = void; -#endif // __cplusplus < 201703l - -template -static constexpr bool CtorCompilesFor_A = false; -template -static constexpr bool - CtorCompilesFor_A{std::declval()})>> = true; -static_assert(CtorCompilesFor_A, "CtorCompilesFor_A"); -static_assert(!CtorCompilesFor_A, "!CtorCompilesFor_A"); - -template -static constexpr bool CtorCompilesFor_B = false; -template -static constexpr bool CtorCompilesFor_B{N})>> = true; -static_assert(!CtorCompilesFor_B, "!CtorCompilesFor_B"); - -template -static constexpr bool CtorCompilesFor_C = false; -template -static constexpr bool CtorCompilesFor_C< - U, void_t{std::declval>()})>> = - true; -static_assert(!CtorCompilesFor_C, "CtorCompilesFor_C"); - -template -static constexpr bool DefaultCtorCompilesFor = false; -template -static constexpr bool DefaultCtorCompilesFor{})>> = true; -static_assert(!DefaultCtorCompilesFor, "!DefaultCtorCompilesFor"); - -template -static constexpr bool StrictHelperCompilesFor = false; -template -static constexpr bool - StrictHelperCompilesFor()))>> = true; -static_assert(StrictHelperCompilesFor>, - "StrictHelperCompilesFor>"); -static_assert(!StrictHelperCompilesFor>, - "!StrictHelperCompilesFor>"); -static_assert(!StrictHelperCompilesFor>, - "!StrictHelperCompilesFor>"); -static_assert(!StrictHelperCompilesFor, "!StrictHelperCompilesFor"); - -template -static constexpr bool HelperCompilesFor = false; -template -static constexpr bool - HelperCompilesFor()))>> = true; -static_assert(HelperCompilesFor>, - "HelperCompilesFor>"); -static_assert(!HelperCompilesFor>, - "!HelperCompilesFor>"); -static_assert(!HelperCompilesFor>, - "!HelperCompilesFor>"); -static_assert(HelperCompilesFor, "HelperCompilesFor"); - -template -static constexpr bool StrictHelperConstCompilesFor = false; -template -static constexpr bool - StrictHelperConstCompilesFor()))>> = true; -static_assert(StrictHelperConstCompilesFor>, - "StrictHelperCompilesFor>"); -static_assert(!StrictHelperConstCompilesFor, "!StrictHelperCompilesFor");