1818
1919#include < gsl/pointers> // for not_null, operator<, operator<=, operator>
2020
21- #include < algorithm> // for addressof
22- #include < cstdint> // for uint16_t
23- #include < memory> // for shared_ptr, make_shared, operator<, opera...
24- #include < sstream> // for operator<<, ostringstream, basic_ostream:...
25- #include < string> // for basic_string, operator==, string, operator<<
26- #include < typeinfo> // for type_info
27- #include < variant> // for variant, monostate, get
21+ #include < algorithm> // for addressof
22+ #include < cstdint> // for uint16_t
23+ #include < memory> // for shared_ptr, make_shared, operator<, opera...
24+ #include < sstream> // for operator<<, ostringstream, basic_ostream:...
25+ #include < string> // for basic_string, operator==, string, operator<<
26+ #include < type_traits> // for declval
27+ #include < typeinfo> // for type_info
28+ #include < variant> // for variant, monostate, get
2829
2930#include " deathTestCommon.h"
3031using namespace gsl ;
3132
33+ #if __cplusplus >= 201703l
34+ using std::void_t ;
35+ #else // __cplusplus >= 201703l
36+ template <class ...>
37+ using void_t = void ;
38+ #endif // __cplusplus < 201703l
39+
3240struct MyBase
3341{
3442};
@@ -141,16 +149,39 @@ bool helper_const(not_null<const int*> p) { return *p == 12; }
141149int * return_pointer () { return nullptr ; }
142150} // namespace
143151
152+ template <typename U, typename = void >
153+ static constexpr bool CtorCompilesFor_A = false ;
154+ template <typename U>
155+ static constexpr bool
156+ CtorCompilesFor_A<U, void_t <decltype (gsl::not_null<void *>{std::declval<U>()})>> = true ;
157+
158+ template <typename U, int N, typename = void >
159+ static constexpr bool CtorCompilesFor_B = false ;
160+ template <typename U, int N>
161+ static constexpr bool CtorCompilesFor_B<U, N, void_t <decltype (gsl::not_null<U>{N})>> = true ;
162+
163+ template <typename U, typename = void >
164+ static constexpr bool DefaultCtorCompilesFor = false ;
165+ template <typename U>
166+ static constexpr bool DefaultCtorCompilesFor<U, void_t <decltype (gsl::not_null<U>{})>> = true ;
167+
168+ template <typename U, typename = void >
169+ static constexpr bool CtorCompilesFor_C = false ;
170+ template <typename U>
171+ static constexpr bool
172+ CtorCompilesFor_C<U, void_t <decltype (gsl::not_null<U*>{std::declval<std::unique_ptr<U>>()})>> =
173+ true ;
174+
144175TEST (notnull_tests, TestNotNullConstructors)
145176{
146177 {
147- #ifdef CONFIRM_COMPILATION_ERRORS
148- not_null<int *> p = nullptr ; // yay...does not compile!
149- not_null<std::vector<char >*> p1 = 0 ; // yay...does not compile!
150- not_null<int *> p2; // yay...does not compile!
151- std::unique_ptr<int > up = std::make_unique<int >(120 );
152- not_null<int *> p3 = up;
178+ static_assert (CtorCompilesFor_A<void *>, " CtorCompilesFor_A<void*>" );
179+ static_assert (!CtorCompilesFor_A<std::nullptr_t >, " !CtorCompilesFor_A<std::nullptr_t>" );
180+ static_assert (!CtorCompilesFor_B<void *, 0 >, " !CtorCompilesFor_B<void*, 0>" );
181+ static_assert (!DefaultCtorCompilesFor<void *>, " !DefaultCtorCompilesFor<void*>" );
182+ static_assert (!CtorCompilesFor_C<int >, " CtorCompilesFor_C<int>" );
153183
184+ #ifdef CONFIRM_COMPILATION_ERRORS
154185 // Forbid non-nullptr assignable types
155186 not_null<std::vector<int >> f (std::vector<int >{1 });
156187 not_null<int > z (10 );
@@ -276,6 +307,27 @@ TEST(notnull_tests, TestNotNullostream)
276307 ostream_helper<std::string>(" string" );
277308}
278309
310+ template <typename U, typename V, typename = void >
311+ static constexpr bool AssignmentCompilesFor = false ;
312+ template <typename U, typename V>
313+ static constexpr bool
314+ AssignmentCompilesFor<U, V,
315+ void_t <decltype (std::declval<gsl::not_null<U*>&>().operator =(
316+ std::declval<gsl::not_null<V*>&>()))>> = true ;
317+
318+ template <typename U, typename V, typename = void >
319+ static constexpr bool SCastCompilesFor = false ;
320+ template <typename U, typename V>
321+ static constexpr bool
322+ SCastCompilesFor<U, V, void_t <decltype (static_cast <U*>(std::declval<gsl::not_null<V*>&>()))>> =
323+ true ;
324+
325+ template <typename U, typename V, typename = void >
326+ static constexpr bool RCastCompilesFor = false ;
327+ template <typename U, typename V>
328+ static constexpr bool RCastCompilesFor<
329+ U, V, void_t <decltype (reinterpret_cast <U*>(std::declval<gsl::not_null<V*>&>()))>> = true ;
330+
279331TEST (notnull_tests, TestNotNullCasting)
280332{
281333 MyBase base;
@@ -288,15 +340,30 @@ TEST(notnull_tests, TestNotNullCasting)
288340 q = p; // allowed with heterogeneous copy ctor
289341 EXPECT_TRUE (q == p);
290342
291- #ifdef CONFIRM_COMPILATION_ERRORS
292- q = u; // no viable conversion possible between MyBase* and Unrelated*
293- p = q; // not possible to implicitly convert MyBase* to MyDerived*
343+ static_assert (AssignmentCompilesFor<MyBase, MyDerived>,
344+ " AssignmentCompilesFor<MyBase, MyDerived>" );
345+ static_assert (!AssignmentCompilesFor<MyBase, Unrelated>,
346+ " !AssignmentCompilesFor<MyBase, Unrelated>" );
347+ static_assert (!AssignmentCompilesFor<Unrelated, MyDerived>,
348+ " !AssignmentCompilesFor<Unrelated, MyDerived>" );
349+ static_assert (!AssignmentCompilesFor<MyDerived, MyBase>,
350+ " !AssignmentCompilesFor<MyDerived, MyBase>" );
351+
352+ static_assert (SCastCompilesFor<MyDerived, MyDerived>, " SCastCompilesFor<MyDerived, MyDerived>" );
353+ static_assert (SCastCompilesFor<MyBase, MyDerived>, " SCastCompilesFor<MyBase, MyDerived>" );
354+ static_assert (!SCastCompilesFor<MyDerived, MyBase>, " !SCastCompilesFor<MyDerived, MyBase>" );
355+ static_assert (!SCastCompilesFor<Unrelated, MyDerived>,
356+ " !SCastCompilesFor<Unrelated, MyDerived>" );
357+ static_assert (!RCastCompilesFor<MyDerived, MyDerived>,
358+ " !SCastCompilesFor<MyDerived, MyDerived>" );
359+ static_assert (!RCastCompilesFor<Unrelated, MyDerived>,
360+ " !SCastCompilesFor<Unrelated, MyDerived>" );
294361
295- not_null<Unrelated*> r = p;
296- not_null<Unrelated*> s = reinterpret_cast <Unrelated*>(p);
297- #endif
298362 not_null<Unrelated*> t (reinterpret_cast <Unrelated*>(p.get ()));
299363 EXPECT_TRUE (reinterpret_cast <void *>(p.get ()) == reinterpret_cast <void *>(t.get ()));
364+
365+ (void ) static_cast <MyDerived*>(p);
366+ (void ) static_cast <MyBase*>(p);
300367}
301368
302369TEST (notnull_tests, TestNotNullAssignment)
@@ -438,6 +505,18 @@ TEST(notnull_tests, TestNotNullCustomPtrComparison)
438505
439506#if defined(__cplusplus) && (__cplusplus >= 201703L)
440507
508+ template <typename U, typename = void >
509+ static constexpr bool TypeDeductionCtorCompilesFor = false ;
510+ template <typename U>
511+ static constexpr bool
512+ TypeDeductionCtorCompilesFor<U, void_t <decltype (not_null{std::declval<U>()})>> = true ;
513+
514+ template <typename U, typename = void >
515+ static constexpr bool TypeDeductionHelperCompilesFor = false ;
516+ template <typename U>
517+ static constexpr bool
518+ TypeDeductionHelperCompilesFor<U, void_t <decltype (helper(not_null{std::declval<U>()}))>> = true ;
519+
441520TEST (notnull_tests, TestNotNullConstructorTypeDeduction)
442521{
443522 {
@@ -454,9 +533,9 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
454533 const int i = 42 ;
455534
456535 not_null x{&i};
457- # ifdef CONFIRM_COMPILATION_ERRORS
458- helper (not_null{&i});
459- # endif
536+ static_assert (TypeDeductionHelperCompilesFor< int *>, " TypeDeductionHelperCompilesFor<int*> " );
537+ static_assert (!TypeDeductionHelperCompilesFor< const int *>,
538+ " !TypeDeductionHelperCompilesFor<const int*> " );
460539 helper_const (not_null{&i});
461540
462541 EXPECT_TRUE (*x == 42 );
@@ -478,9 +557,6 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
478557 const int * p = &i;
479558
480559 not_null x{p};
481- #ifdef CONFIRM_COMPILATION_ERRORS
482- helper (not_null{p});
483- #endif
484560 helper_const (not_null{p});
485561
486562 EXPECT_TRUE (*x == 42 );
@@ -515,12 +591,15 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
515591 EXPECT_DEATH (helper_const (not_null{p}), expected);
516592 }
517593
518- #ifdef CONFIRM_COMPILATION_ERRORS
519- {
520- not_null x{nullptr };
521- helper (not_null{nullptr });
522- helper_const (not_null{nullptr });
523- }
594+ static_assert (TypeDeductionCtorCompilesFor<void *>, " TypeDeductionCtorCompilesFor<void*>" );
595+ #if defined(_MSC_VER) && !defined(__clang__)
596+ // Fails on gcc, clang, xcode, VS clang with
597+ // "error : no type named 'type' in 'std::enable_if<false>'; 'enable_if' cannot be used to
598+ // disable this declaration"
599+ static_assert (!TypeDeductionCtorCompilesFor<std::nullptr_t >,
600+ " !TypeDeductionCtorCompilesFor<std::nullptr_t>" );
601+ static_assert (!TypeDeductionHelperCompilesFor<std::nullptr_t >,
602+ " !TypeDeductionHelperCompilesFor<std::nullptr_t>" );
524603#endif
525604}
526605
@@ -536,6 +615,11 @@ TEST(notnull_tests, TestVariantEmplace)
536615}
537616#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
538617
618+ template <typename U, typename = void >
619+ static constexpr bool HelperCompilesFor = false ;
620+ template <typename U>
621+ static constexpr bool HelperCompilesFor<U, void_t <decltype (helper(std::declval<U>()))>> = true ;
622+
539623TEST (notnull_tests, TestMakeNotNull)
540624{
541625 {
@@ -552,9 +636,8 @@ TEST(notnull_tests, TestMakeNotNull)
552636 const int i = 42 ;
553637
554638 const auto x = make_not_null (&i);
555- #ifdef CONFIRM_COMPILATION_ERRORS
556- helper (make_not_null (&i));
557- #endif
639+ static_assert (HelperCompilesFor<gsl::not_null<int *>>,
640+ " HelperCompilesFor<gsl::not_null<int*>>" );
558641 helper_const (make_not_null (&i));
559642
560643 EXPECT_TRUE (*x == 42 );
@@ -576,9 +659,8 @@ TEST(notnull_tests, TestMakeNotNull)
576659 const int * p = &i;
577660
578661 const auto x = make_not_null (p);
579- #ifdef CONFIRM_COMPILATION_ERRORS
580- helper (make_not_null (p));
581- #endif
662+ static_assert (!HelperCompilesFor<gsl::not_null<const int *>>,
663+ " !HelperCompilesFor<gsl::not_null<const int*>>" );
582664 helper_const (make_not_null (p));
583665
584666 EXPECT_TRUE (*x == 42 );
0 commit comments