Skip to content

Commit 8de751c

Browse files
committed
Use if constexpr
Signed-off-by: cyy <cyyever@outlook.com>
1 parent 228f563 commit 8de751c

File tree

6 files changed

+53
-36
lines changed

6 files changed

+53
-36
lines changed

include/pybind11/cast.h

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
3535

3636
PYBIND11_WARNING_DISABLE_MSVC(4127)
37+
#if PYBIND11_HAS_IF_CONSTEXPR
38+
PYBIND11_WARNING_DISABLE_MSVC(4702)
39+
#endif
3740

3841
PYBIND11_NAMESPACE_BEGIN(detail)
3942

@@ -244,24 +247,25 @@ struct type_caster<T, enable_if_t<std::is_arithmetic<T>::value && !is_std_char_t
244247
return false;
245248
}
246249

247-
#if !defined(PYPY_VERSION)
248-
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
249-
#else
250-
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
251-
// while CPython only considers the existence of `nb_index`/`__index__`.
252-
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
253-
#endif
254-
255-
if (std::is_floating_point<T>::value) {
250+
if PYBIND11_IF_CONSTEXPR (std::is_floating_point<T>::value) {
256251
if (convert || PyFloat_Check(src.ptr())) {
257252
py_value = (py_type) PyFloat_AsDouble(src.ptr());
258253
} else {
259254
return false;
260255
}
261-
} else if (PyFloat_Check(src.ptr())
262-
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
263-
return false;
264256
} else {
257+
#if !defined(PYPY_VERSION)
258+
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
259+
#else
260+
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
261+
// while CPython only considers the existence of `nb_index`/`__index__`.
262+
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
263+
#endif
264+
if (PyFloat_Check(src.ptr())
265+
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
266+
return false;
267+
}
268+
265269
handle src_or_index = src;
266270
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
267271
#if defined(PYPY_VERSION)
@@ -277,7 +281,7 @@ struct type_caster<T, enable_if_t<std::is_arithmetic<T>::value && !is_std_char_t
277281
}
278282
}
279283
#endif
280-
if (std::is_unsigned<py_type>::value) {
284+
if PYBIND11_IF_CONSTEXPR (std::is_unsigned<py_type>::value) {
281285
py_value = as_unsigned<py_type>(src_or_index.ptr());
282286
} else { // signed integer:
283287
py_value = sizeof(T) <= sizeof(long)
@@ -516,7 +520,7 @@ struct string_caster {
516520

517521
// For UTF-8 we avoid the need for a temporary `bytes` object by using
518522
// `PyUnicode_AsUTF8AndSize`.
519-
if (UTF_N == 8) {
523+
if PYBIND11_IF_CONSTEXPR (UTF_N == 8) {
520524
Py_ssize_t size = -1;
521525
const auto *buffer
522526
= reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size));
@@ -543,7 +547,7 @@ struct string_caster {
543547
= reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr()));
544548
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
545549
// Skip BOM for UTF-16/32
546-
if (UTF_N > 8) {
550+
if PYBIND11_IF_CONSTEXPR (UTF_N > 8) {
547551
buffer++;
548552
length--;
549553
}
@@ -670,7 +674,7 @@ struct type_caster<CharT, enable_if_t<is_std_char_type<CharT>::value>> {
670674
}
671675

672676
static handle cast(CharT src, return_value_policy policy, handle parent) {
673-
if (std::is_same<char, CharT>::value) {
677+
if PYBIND11_IF_CONSTEXPR (std::is_same<char, CharT>::value) {
674678
handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr);
675679
if (!s) {
676680
throw error_already_set();

include/pybind11/detail/common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@
9595
# define PYBIND11_HAS_STD_LAUNDER 0
9696
#endif
9797

98+
#if defined(__cpp_if_constexpr)
99+
# define PYBIND11_HAS_IF_CONSTEXPR 1
100+
# define PYBIND11_IF_CONSTEXPR constexpr
101+
#else
102+
# define PYBIND11_HAS_IF_CONSTEXPR 0
103+
# define PYBIND11_IF_CONSTEXPR
104+
#endif
105+
98106
#if defined(PYBIND11_CPP20)
99107
# define PYBIND11_CONSTINIT constinit
100108
# define PYBIND11_DTOR_CONSTEXPR constexpr

include/pybind11/eigen/tensor.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
3333
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
3434

3535
PYBIND11_WARNING_DISABLE_MSVC(4127)
36+
#if PYBIND11_HAS_IF_CONSTEXPR
37+
PYBIND11_WARNING_DISABLE_MSVC(4702)
38+
#endif
3639

3740
PYBIND11_NAMESPACE_BEGIN(detail)
3841

@@ -274,10 +277,9 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
274277
bool writeable = false;
275278
switch (policy) {
276279
case return_value_policy::move:
277-
if (std::is_const<C>::value) {
280+
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
278281
pybind11_fail("Cannot move from a constant reference");
279282
}
280-
281283
src = Helper::alloc(std::move(*src));
282284

283285
parent_object
@@ -286,13 +288,12 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
286288
break;
287289

288290
case return_value_policy::take_ownership:
289-
if (std::is_const<C>::value) {
291+
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
290292
// This cast is ugly, and might be UB in some cases, but we don't have an
291293
// alternative here as we must free that memory
292294
Helper::free(const_cast<Type *>(src));
293295
pybind11_fail("Cannot take ownership of a const reference");
294296
}
295-
296297
parent_object
297298
= capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
298299
writeable = true;

include/pybind11/pybind11.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ class cpp_function : public function {
399399
auto *rec = unique_rec.get();
400400

401401
/* Store the capture object directly in the function record if there is enough space */
402-
if (sizeof(capture) <= sizeof(rec->data)) {
402+
if PYBIND11_IF_CONSTEXPR (sizeof(capture) <= sizeof(rec->data)) {
403403
/* Without these pragmas, GCC warns that there might not be
404404
enough space to use the placement new operator. However, the
405405
'if' statement above ensures that this is the case. */
@@ -417,7 +417,7 @@ class cpp_function : public function {
417417

418418
// UB without std::launder, but without breaking ABI and/or
419419
// a significant refactoring it's "impossible" to solve.
420-
if (!std::is_trivially_destructible<capture>::value) {
420+
if PYBIND11_IF_CONSTEXPR (!std::is_trivially_destructible<capture>::value) {
421421
rec->free_data = [](function_record *r) {
422422
auto data = capture::from_data(r->data);
423423
(void) data; // suppress "unused variable" warnings
@@ -2189,7 +2189,7 @@ class class_ : public detail::generic_type {
21892189

21902190
generic_type::initialize(record);
21912191

2192-
if (has_alias) {
2192+
if PYBIND11_IF_CONSTEXPR (has_alias) {
21932193
with_internals([&](internals &internals) {
21942194
auto &local_internals = get_local_internals();
21952195
if (record.module_local) {
@@ -2696,7 +2696,8 @@ inline str enum_name(handle arg) {
26962696
struct enum_base {
26972697
enum_base(const handle &base, const handle &parent) : m_base(base), m_parent(parent) {}
26982698

2699-
PYBIND11_NOINLINE void init(bool is_arithmetic, bool is_convertible) {
2699+
template <bool is_arithmetic, bool is_convertible>
2700+
PYBIND11_NOINLINE void init() {
27002701
m_base.attr("__entries") = dict();
27012702
auto property = handle((PyObject *) &PyProperty_Type);
27022703
auto static_property = handle((PyObject *) get_internals().static_property_type);
@@ -2802,11 +2803,11 @@ struct enum_base {
28022803
arg("other"), \
28032804
pos_only())
28042805

2805-
if (is_convertible) {
2806+
if PYBIND11_IF_CONSTEXPR (is_convertible) {
28062807
PYBIND11_ENUM_OP_CONV_LHS("__eq__", !b.is_none() && a.equal(b));
28072808
PYBIND11_ENUM_OP_CONV_LHS("__ne__", b.is_none() || !a.equal(b));
28082809

2809-
if (is_arithmetic) {
2810+
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
28102811
PYBIND11_ENUM_OP_CONV("__lt__", a < b);
28112812
PYBIND11_ENUM_OP_CONV("__gt__", a > b);
28122813
PYBIND11_ENUM_OP_CONV("__le__", a <= b);
@@ -2827,7 +2828,7 @@ struct enum_base {
28272828
PYBIND11_ENUM_OP_STRICT("__eq__", int_(a).equal(int_(b)), return false);
28282829
PYBIND11_ENUM_OP_STRICT("__ne__", !int_(a).equal(int_(b)), return true);
28292830

2830-
if (is_arithmetic) {
2831+
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
28312832
#define PYBIND11_THROW throw type_error("Expected an enumeration of matching type!");
28322833
PYBIND11_ENUM_OP_STRICT("__lt__", int_(a) < int_(b), PYBIND11_THROW);
28332834
PYBIND11_ENUM_OP_STRICT("__gt__", int_(a) > int_(b), PYBIND11_THROW);
@@ -2946,7 +2947,7 @@ class enum_ : public class_<Type> {
29462947

29472948
constexpr bool is_arithmetic = detail::any_of<std::is_same<arithmetic, Extra>...>::value;
29482949
constexpr bool is_convertible = std::is_convertible<Type, Underlying>::value;
2949-
m_base.init(is_arithmetic, is_convertible);
2950+
m_base.init<is_arithmetic, is_convertible>();
29502951

29512952
def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
29522953
def_property_readonly("value", [](Type value) { return (Scalar) value; }, pos_only());

include/pybind11/pytypes.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
3535

3636
PYBIND11_WARNING_DISABLE_MSVC(4127)
37+
#if PYBIND11_HAS_IF_CONSTEXPR
38+
PYBIND11_WARNING_DISABLE_MSVC(4702)
39+
#endif
3740

3841
/* A few forward declarations */
3942
class handle;
@@ -1859,7 +1862,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
18591862
// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes).
18601863
template <typename Unsigned>
18611864
Unsigned as_unsigned(PyObject *o) {
1862-
if (sizeof(Unsigned) <= sizeof(unsigned long)) {
1865+
if PYBIND11_IF_CONSTEXPR (sizeof(Unsigned) <= sizeof(unsigned long)) {
18631866
unsigned long v = PyLong_AsUnsignedLong(o);
18641867
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
18651868
}
@@ -1876,14 +1879,14 @@ class int_ : public object {
18761879
template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
18771880
// NOLINTNEXTLINE(google-explicit-constructor)
18781881
int_(T value) {
1879-
if (sizeof(T) <= sizeof(long)) {
1880-
if (std::is_signed<T>::value) {
1882+
if PYBIND11_IF_CONSTEXPR (sizeof(T) <= sizeof(long)) {
1883+
if PYBIND11_IF_CONSTEXPR (std::is_signed<T>::value) {
18811884
m_ptr = PyLong_FromLong((long) value);
18821885
} else {
18831886
m_ptr = PyLong_FromUnsignedLong((unsigned long) value);
18841887
}
18851888
} else {
1886-
if (std::is_signed<T>::value) {
1889+
if PYBIND11_IF_CONSTEXPR (std::is_signed<T>::value) {
18871890
m_ptr = PyLong_FromLongLong((long long) value);
18881891
} else {
18891892
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);

include/pybind11/stl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ struct set_caster {
203203

204204
template <typename T>
205205
static handle cast(T &&src, return_value_policy policy, handle parent) {
206-
if (!std::is_lvalue_reference<T>::value) {
206+
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
207207
policy = return_value_policy_override<Key>::policy(policy);
208208
}
209209
pybind11::set s;
@@ -272,7 +272,7 @@ struct map_caster {
272272
dict d;
273273
return_value_policy policy_key = policy;
274274
return_value_policy policy_value = policy;
275-
if (!std::is_lvalue_reference<T>::value) {
275+
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
276276
policy_key = return_value_policy_override<Key>::policy(policy_key);
277277
policy_value = return_value_policy_override<Value>::policy(policy_value);
278278
}
@@ -341,7 +341,7 @@ struct list_caster {
341341
public:
342342
template <typename T>
343343
static handle cast(T &&src, return_value_policy policy, handle parent) {
344-
if (!std::is_lvalue_reference<T>::value) {
344+
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
345345
policy = return_value_policy_override<Value>::policy(policy);
346346
}
347347
list l(src.size());
@@ -534,7 +534,7 @@ struct optional_caster {
534534
if (!src) {
535535
return none().release();
536536
}
537-
if (!std::is_lvalue_reference<T>::value) {
537+
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
538538
policy = return_value_policy_override<Value>::policy(policy);
539539
}
540540
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)

0 commit comments

Comments
 (0)