mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55:11 +00:00
Use if constexpr
This commit is contained in:
parent
7e418f4924
commit
efbd12c6a5
@ -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,46 +141,47 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
||||
#else
|
||||
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
|
||||
// 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 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 (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)
|
||||
object index;
|
||||
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
||||
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
||||
if (!index) {
|
||||
PyErr_Clear();
|
||||
if (!convert)
|
||||
return false;
|
||||
} else {
|
||||
src_or_index = index;
|
||||
}
|
||||
}
|
||||
#if !defined(PYPY_VERSION)
|
||||
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
||||
#else
|
||||
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
|
||||
// while CPython only considers the existence of `nb_index`/`__index__`.
|
||||
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
|
||||
#endif
|
||||
if (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)
|
||||
? (py_type) PyLong_AsLong(src_or_index.ptr())
|
||||
: (py_type) PYBIND11_LONG_AS_LONGLONG(src_or_index.ptr());
|
||||
if (PyFloat_Check(src.ptr())
|
||||
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
handle src_or_index = src;
|
||||
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
|
||||
#if defined(PYPY_VERSION)
|
||||
object index;
|
||||
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
||||
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
||||
if (!index) {
|
||||
PyErr_Clear();
|
||||
if (!convert)
|
||||
return false;
|
||||
} else {
|
||||
src_or_index = index;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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)
|
||||
? (py_type) PyLong_AsLong(src_or_index.ptr())
|
||||
: (py_type) PYBIND11_LONG_AS_LONGLONG(src_or_index.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
// Python API reported an error
|
||||
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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; });
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user