44
55#include < Python.h>
66
7+ #include < concepts>
78#include < functional>
89#include < type_traits>
910
11+ template <typename T>
12+ concept IsPyObject = std::same_as<PyObject, T>;
13+
1014template <typename T>
1115class RefBase {
1216 public:
@@ -18,7 +22,8 @@ class RefBase {
1822 }
1923
2024 template <typename X = T>
21- operator std::enable_if_t <!std::is_same_v<X, PyObject>, PyObject*>() const {
25+ requires (!IsPyObject<X>)
26+ operator PyObject*() const {
2227 return getObj ();
2328 }
2429
@@ -63,9 +68,8 @@ void decref_total(PyInterpreterState* ts);
6368 * (as opposed to in a comment).
6469 *
6570 */
66- template <
67- typename T = PyObject,
68- typename = std::enable_if_t <!std::is_pointer_v<T>>>
71+ template <typename T = PyObject>
72+ requires (!std::is_pointer_v<T>)
6973class BorrowedRef : public RefBase<T> {
7074 public:
7175 using RefBase<T>::RefBase;
@@ -78,16 +82,13 @@ class BorrowedRef : public RefBase<T> {
7882 //
7983 // PyObject doesn't have "subclasses" in the same way that C++ does, so we
8084 // can't do a std::is_base_of_v<PyObject, X> check here.
81- template <
82- typename X = T,
83- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
85+ template <typename X = T>
86+ requires (!IsPyObject<X>)
8487 BorrowedRef (PyObject* ptr) : BorrowedRef (reinterpret_cast <X*>(ptr)) {}
8588
8689 // Allow conversion from any BorrowedRef<V> to BorrowedRef<PyObject>.
87- template <
88- typename V,
89- typename X = T,
90- typename = std::enable_if_t <std::is_same_v<X, PyObject>>>
90+ template <typename V, typename X = T>
91+ requires IsPyObject<X>
9192 BorrowedRef (const BorrowedRef<V>& other)
9293 : BorrowedRef (reinterpret_cast <PyObject*>(other.get ())) {}
9394
@@ -162,9 +163,8 @@ struct std::hash<BorrowedRef<T>> {
162163 * `MyPyTuple_SetItem`.
163164 *
164165 */
165- template <
166- typename T = PyObject,
167- typename = std::enable_if_t <!std::is_pointer_v<T>>>
166+ template <typename T = PyObject>
167+ requires (!std::is_pointer_v<T>)
168168class Ref : public RefBase<T> {
169169 public:
170170 using RefBase<T>::RefBase;
@@ -179,9 +179,8 @@ class Ref : public RefBase<T> {
179179 other.ptr_ = nullptr ;
180180 }
181181
182- template <
183- typename X = T,
184- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
182+ template <typename X = T>
183+ requires (!IsPyObject<X>)
185184 Ref (Ref<>&& other) {
186185 ptr_ = reinterpret_cast <T*>(other.release ());
187186 }
@@ -196,9 +195,8 @@ class Ref : public RefBase<T> {
196195 return *this ;
197196 }
198197
199- template <
200- typename X = T,
201- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
198+ template <typename X = T>
199+ requires (!IsPyObject<X>)
202200 Ref& operator =(Ref<>&& other) {
203201 if (this ->get () == reinterpret_cast <T*>(other.get ())) {
204202 return *this ;
@@ -214,9 +212,8 @@ class Ref : public RefBase<T> {
214212 ptr_ = obj;
215213 }
216214
217- template <
218- typename X = T,
219- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
215+ template <typename X = T>
216+ requires (!IsPyObject<X>)
220217 void reset (PyObject* obj) {
221218 reset (reinterpret_cast <T*>(obj));
222219 }
@@ -229,9 +226,8 @@ class Ref : public RefBase<T> {
229226 return Ref (obj, CreateTag{});
230227 }
231228
232- template <
233- typename X = T,
234- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
229+ template <typename X = T>
230+ requires (!IsPyObject<X>)
235231 static Ref steal (PyObject* obj) {
236232 return Ref (reinterpret_cast <T*>(obj), StealTag{});
237233 }
@@ -241,9 +237,8 @@ class Ref : public RefBase<T> {
241237 template <typename V>
242238 static Ref steal (const Ref<V>&) = delete ;
243239
244- template <
245- typename X = T,
246- typename = std::enable_if_t <!std::is_same_v<X, PyObject>>>
240+ template <typename X = T>
241+ requires (!IsPyObject<X>)
247242 static Ref create (PyObject* obj) {
248243 return Ref (reinterpret_cast <T*>(obj), CreateTag{});
249244 }
0 commit comments