[PATCH] D95498: ADT: Add SFINAE to the generic IntrusiveRefCntPtr constructors

Duncan P. N. Exon Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 26 19:58:39 PST 2021


dexonsmith created this revision.
dexonsmith added a reviewer: dblaikie.
Herald added a subscriber: ributzka.
dexonsmith requested review of this revision.
Herald added a project: LLVM.

Add an `enable_if` to the generic `IntrusiveRefCntPtr` constructors so
that std::is_convertible gives an honest answer when the underlying
pointers cannot be converted.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95498

Files:
  llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
  llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp


Index: llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
===================================================================
--- llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
+++ llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
@@ -96,4 +96,46 @@
   EXPECT_TRUE(Retained);
 }
 
+TEST(IntrusiveRefCntPtr, ConstructorSFINAE) {
+  struct X {};
+  struct Y : X {};
+  struct Z {};
+  static_assert(std::is_convertible<IntrusiveRefCntPtr<X> &&,
+                                    IntrusiveRefCntPtr<X>>::value,
+                "X -> X is okay");
+  static_assert(std::is_convertible<const IntrusiveRefCntPtr<X> &,
+                                    IntrusiveRefCntPtr<X>>::value,
+                "X -> X is okay");
+  static_assert(
+      std::is_convertible<std::unique_ptr<X>, IntrusiveRefCntPtr<X>>::value,
+      "X -> X is okay");
+  static_assert(std::is_convertible<IntrusiveRefCntPtr<Y> &&,
+                                    IntrusiveRefCntPtr<X>>::value,
+                "Y -> X is okay");
+  static_assert(std::is_convertible<const IntrusiveRefCntPtr<Y> &,
+                                    IntrusiveRefCntPtr<X>>::value,
+                "Y -> X is okay");
+  static_assert(
+      std::is_convertible<std::unique_ptr<Y>, IntrusiveRefCntPtr<X>>::value,
+      "Y -> X is okay");
+  static_assert(!std::is_convertible<IntrusiveRefCntPtr<X> &&,
+                                     IntrusiveRefCntPtr<Y>>::value,
+                "X -> Y should be rejected with SFINAE");
+  static_assert(!std::is_convertible<const IntrusiveRefCntPtr<X> &,
+                                     IntrusiveRefCntPtr<Y>>::value,
+                "X -> Y should be rejected with SFINAE");
+  static_assert(
+      !std::is_convertible<std::unique_ptr<X>, IntrusiveRefCntPtr<Y>>::value,
+      "X -> Y should be rejected with SFINAE");
+  static_assert(!std::is_convertible<IntrusiveRefCntPtr<X> &&,
+                                     IntrusiveRefCntPtr<Z>>::value,
+                "X -> Z should be rejected with SFINAE");
+  static_assert(!std::is_convertible<const IntrusiveRefCntPtr<X> &,
+                                     IntrusiveRefCntPtr<Z>>::value,
+                "X -> Z should be rejected with SFINAE");
+  static_assert(
+      !std::is_convertible<std::unique_ptr<X>, IntrusiveRefCntPtr<Z>>::value,
+      "X -> Z should be rejected with SFINAE");
+}
+
 } // end namespace llvm
Index: llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
===================================================================
--- llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
+++ llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -171,17 +171,20 @@
   IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); }
   IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; }
 
-  template <class X>
+  template <class X,
+            std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true>
   IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> &&S) : Obj(S.get()) {
     S.Obj = nullptr;
   }
 
-  template <class X>
+  template <class X,
+            std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true>
   IntrusiveRefCntPtr(std::unique_ptr<X> S) : Obj(S.release()) {
     retain();
   }
 
-  template <class X>
+  template <class X,
+            std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true>
   IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> &S) : Obj(S.get()) {
     retain();
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D95498.319452.patch
Type: text/x-patch
Size: 3437 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210127/606839be/attachment.bin>


More information about the llvm-commits mailing list