Skip to content

Commit dd923c5

Browse files
authored
[3.11] GH-92898: Make _Py_Cast C++ version compatible with cast operator (gh-92951) (gh-93049)
1 parent d9a48d2 commit dd923c5

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

Include/pyport.h

+26-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,32 @@
2626
// _Py_CAST(const PyObject*, expr) fails with a compiler error.
2727
#ifdef __cplusplus
2828
# define _Py_STATIC_CAST(type, expr) static_cast<type>(expr)
29-
# define _Py_CAST(type, expr) \
30-
const_cast<type>(reinterpret_cast<const type>(expr))
29+
30+
extern "C++" {
31+
namespace {
32+
template <typename type, typename expr_type>
33+
inline type _Py_reinterpret_cast_impl(expr_type *expr) {
34+
return reinterpret_cast<type>(expr);
35+
}
36+
37+
template <typename type, typename expr_type>
38+
inline type _Py_reinterpret_cast_impl(expr_type const *expr) {
39+
return reinterpret_cast<type>(const_cast<expr_type *>(expr));
40+
}
41+
42+
template <typename type, typename expr_type>
43+
inline type _Py_reinterpret_cast_impl(expr_type &expr) {
44+
return static_cast<type>(expr);
45+
}
46+
47+
template <typename type, typename expr_type>
48+
inline type _Py_reinterpret_cast_impl(expr_type const &expr) {
49+
return static_cast<type>(const_cast<expr_type &>(expr));
50+
}
51+
} // namespace
52+
}
53+
# define _Py_CAST(type, expr) _Py_reinterpret_cast_impl<type>(expr)
54+
3155
#else
3256
# define _Py_STATIC_CAST(type, expr) ((type)(expr))
3357
# define _Py_CAST(type, expr) ((type)(expr))

Lib/test/_testcppext.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
4040
PyTypeObject *type = Py_TYPE(const_obj);
4141
assert(Py_REFCNT(const_obj) >= 1);
4242

43+
struct PyObjectProxy {
44+
PyObject* obj;
45+
operator PyObject *() { return obj; }
46+
} proxy_obj = { obj };
47+
Py_INCREF(proxy_obj);
48+
Py_DECREF(proxy_obj);
49+
assert(Py_REFCNT(proxy_obj) >= 1);
50+
51+
4352
assert(type == &PyTuple_Type);
4453
assert(PyTuple_GET_SIZE(const_obj) == 2);
4554
PyObject *one = PyTuple_GET_ITEM(const_obj, 0);

0 commit comments

Comments
 (0)