Use if constexpr

This commit is contained in:
cyy 2024-09-29 22:36:45 +08:00
parent 7e418f4924
commit efbd12c6a5
6 changed files with 73 additions and 56 deletions

View File

@ -31,6 +31,9 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
#if PYBIND11_HAS_IF_CONSTEXPR
PYBIND11_WARNING_DISABLE_MSVC(4702)
#endif
PYBIND11_NAMESPACE_BEGIN(detail)
@ -138,6 +141,13 @@ public:
return false;
}
if PYBIND11_IF_CONSTEXPR (std::is_floating_point<T>::value) {
if (convert || PyFloat_Check(src.ptr())) {
py_value = (py_type) PyFloat_AsDouble(src.ptr());
} else {
return false;
}
} else {
#if !defined(PYPY_VERSION)
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
#else
@ -145,17 +155,11 @@ public:
// while CPython only considers the existence of `nb_index`/`__index__`.
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
#endif
if (std::is_floating_point<T>::value) {
if (convert || PyFloat_Check(src.ptr())) {
py_value = (py_type) PyFloat_AsDouble(src.ptr());
} else {
return false;
}
} else if (PyFloat_Check(src.ptr())
if (PyFloat_Check(src.ptr())
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
return false;
} else {
}
handle src_or_index = src;
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
#if defined(PYPY_VERSION)
@ -171,7 +175,7 @@ public:
}
}
#endif
if (std::is_unsigned<py_type>::value) {
if PYBIND11_IF_CONSTEXPR (std::is_unsigned<py_type>::value) {
py_value = as_unsigned<py_type>(src_or_index.ptr());
} else { // signed integer:
py_value = sizeof(T) <= sizeof(long)
@ -405,7 +409,7 @@ struct string_caster {
// For UTF-8 we avoid the need for a temporary `bytes` object by using
// `PyUnicode_AsUTF8AndSize`.
if (UTF_N == 8) {
if PYBIND11_IF_CONSTEXPR (UTF_N == 8) {
Py_ssize_t size = -1;
const auto *buffer
= reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size));
@ -432,7 +436,7 @@ struct string_caster {
= reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr()));
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
// Skip BOM for UTF-16/32
if (UTF_N > 8) {
if PYBIND11_IF_CONSTEXPR (UTF_N > 8) {
buffer++;
length--;
}
@ -559,7 +563,7 @@ public:
}
static handle cast(CharT src, return_value_policy policy, handle parent) {
if (std::is_same<char, CharT>::value) {
if PYBIND11_IF_CONSTEXPR (std::is_same<char, CharT>::value) {
handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr);
if (!s) {
throw error_already_set();

View File

@ -118,6 +118,14 @@
# endif
#endif
#if defined(__cpp_if_constexpr)
# define PYBIND11_HAS_IF_CONSTEXPR 1
# define PYBIND11_IF_CONSTEXPR constexpr
#else
# define PYBIND11_HAS_IF_CONSTEXPR 0
# define PYBIND11_IF_CONSTEXPR
#endif
#if defined(PYBIND11_CPP20)
# define PYBIND11_CONSTINIT constinit
# define PYBIND11_DTOR_CONSTEXPR constexpr

View File

@ -33,6 +33,9 @@ static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
#if PYBIND11_HAS_IF_CONSTEXPR
PYBIND11_WARNING_DISABLE_MSVC(4702)
#endif
PYBIND11_NAMESPACE_BEGIN(detail)
@ -272,10 +275,9 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
bool writeable = false;
switch (policy) {
case return_value_policy::move:
if (std::is_const<C>::value) {
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
pybind11_fail("Cannot move from a constant reference");
}
src = Helper::alloc(std::move(*src));
parent_object
@ -284,13 +286,12 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
break;
case return_value_policy::take_ownership:
if (std::is_const<C>::value) {
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
// This cast is ugly, and might be UB in some cases, but we don't have an
// alternative here as we must free that memory
Helper::free(const_cast<Type *>(src));
pybind11_fail("Cannot take ownership of a const reference");
}
parent_object
= capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
writeable = true;

View File

@ -204,7 +204,7 @@ protected:
auto *rec = unique_rec.get();
/* Store the capture object directly in the function record if there is enough space */
if (sizeof(capture) <= sizeof(rec->data)) {
if PYBIND11_IF_CONSTEXPR (sizeof(capture) <= sizeof(rec->data)) {
/* Without these pragmas, GCC warns that there might not be
enough space to use the placement new operator. However, the
'if' statement above ensures that this is the case. */
@ -222,7 +222,7 @@ protected:
// UB without std::launder, but without breaking ABI and/or
// a significant refactoring it's "impossible" to solve.
if (!std::is_trivially_destructible<capture>::value) {
if PYBIND11_IF_CONSTEXPR (!std::is_trivially_destructible<capture>::value) {
rec->free_data = [](function_record *r) {
auto data = PYBIND11_STD_LAUNDER((capture *) &r->data);
(void) data;
@ -331,7 +331,7 @@ protected:
using FunctionType = Return (*)(Args...);
constexpr bool is_function_ptr
= std::is_convertible<Func, FunctionType>::value && sizeof(capture) == sizeof(void *);
if (is_function_ptr) {
if PYBIND11_IF_CONSTEXPR (is_function_ptr) {
rec->is_stateless = true;
rec->data[1]
= const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
@ -1605,7 +1605,7 @@ public:
generic_type::initialize(record);
if (has_alias) {
if PYBIND11_IF_CONSTEXPR (has_alias) {
with_internals([&](internals &internals) {
auto &instances = record.module_local ? get_local_internals().registered_types_cpp
: internals.registered_types_cpp;
@ -2011,7 +2011,8 @@ inline str enum_name(handle arg) {
struct enum_base {
enum_base(const handle &base, const handle &parent) : m_base(base), m_parent(parent) {}
PYBIND11_NOINLINE void init(bool is_arithmetic, bool is_convertible) {
template<bool is_arithmetic, bool is_convertible>
PYBIND11_NOINLINE void init() {
m_base.attr("__entries") = dict();
auto property = handle((PyObject *) &PyProperty_Type);
auto static_property = handle((PyObject *) get_internals().static_property_type);
@ -2111,11 +2112,11 @@ struct enum_base {
is_method(m_base), \
arg("other"))
if (is_convertible) {
if PYBIND11_IF_CONSTEXPR (is_convertible) {
PYBIND11_ENUM_OP_CONV_LHS("__eq__", !b.is_none() && a.equal(b));
PYBIND11_ENUM_OP_CONV_LHS("__ne__", b.is_none() || !a.equal(b));
if (is_arithmetic) {
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
PYBIND11_ENUM_OP_CONV("__lt__", a < b);
PYBIND11_ENUM_OP_CONV("__gt__", a > b);
PYBIND11_ENUM_OP_CONV("__le__", a <= b);
@ -2135,7 +2136,7 @@ struct enum_base {
PYBIND11_ENUM_OP_STRICT("__eq__", int_(a).equal(int_(b)), return false);
PYBIND11_ENUM_OP_STRICT("__ne__", !int_(a).equal(int_(b)), return true);
if (is_arithmetic) {
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
#define PYBIND11_THROW throw type_error("Expected an enumeration of matching type!");
PYBIND11_ENUM_OP_STRICT("__lt__", int_(a) < int_(b), PYBIND11_THROW);
PYBIND11_ENUM_OP_STRICT("__gt__", int_(a) > int_(b), PYBIND11_THROW);
@ -2242,7 +2243,7 @@ public:
: class_<Type>(scope, name, extra...), m_base(*this, scope) {
constexpr bool is_arithmetic = detail::any_of<std::is_same<arithmetic, Extra>...>::value;
constexpr bool is_convertible = std::is_convertible<Type, Underlying>::value;
m_base.init(is_arithmetic, is_convertible);
m_base.init<is_arithmetic, is_convertible>();
def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
def_property_readonly("value", [](Type value) { return (Scalar) value; });

View File

@ -34,6 +34,9 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
#if PYBIND11_HAS_IF_CONSTEXPR
PYBIND11_WARNING_DISABLE_MSVC(4702)
#endif
/* A few forward declarations */
class handle;
@ -1825,7 +1828,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes).
template <typename Unsigned>
Unsigned as_unsigned(PyObject *o) {
if (sizeof(Unsigned) <= sizeof(unsigned long)) {
if PYBIND11_IF_CONSTEXPR (sizeof(Unsigned) <= sizeof(unsigned long)) {
unsigned long v = PyLong_AsUnsignedLong(o);
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
}
@ -1842,14 +1845,14 @@ public:
template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor)
int_(T value) {
if (sizeof(T) <= sizeof(long)) {
if (std::is_signed<T>::value) {
if PYBIND11_IF_CONSTEXPR (sizeof(T) <= sizeof(long)) {
if PYBIND11_IF_CONSTEXPR (std::is_signed<T>::value) {
m_ptr = PyLong_FromLong((long) value);
} else {
m_ptr = PyLong_FromUnsignedLong((unsigned long) value);
}
} else {
if (std::is_signed<T>::value) {
if PYBIND11_IF_CONSTEXPR (std::is_signed<T>::value) {
m_ptr = PyLong_FromLongLong((long long) value);
} else {
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);

View File

@ -189,7 +189,7 @@ public:
template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) {
if (!std::is_lvalue_reference<T>::value) {
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
policy = return_value_policy_override<Key>::policy(policy);
}
pybind11::set s;
@ -256,7 +256,7 @@ public:
dict d;
return_value_policy policy_key = policy;
return_value_policy policy_value = policy;
if (!std::is_lvalue_reference<T>::value) {
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
policy_key = return_value_policy_override<Key>::policy(policy_key);
policy_value = return_value_policy_override<Value>::policy(policy_value);
}
@ -324,7 +324,7 @@ private:
public:
template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) {
if (!std::is_lvalue_reference<T>::value) {
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
policy = return_value_policy_override<Value>::policy(policy);
}
list l(src.size());
@ -513,7 +513,7 @@ struct optional_caster {
if (!src) {
return none().release();
}
if (!std::is_lvalue_reference<T>::value) {
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
policy = return_value_policy_override<Value>::policy(policy);
}
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)