mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Untangle cast logic to not implicitly require castability (#1442)
The current code requires implicitly that integral types are cast-able to floating point. In case of strongly-typed integrals (e.g. as explained at http://www.ilikebigbits.com/blog/2014/5/6/type-safe-identifiers-in-c) this is not always the case. This commit uses SFINAE to move the numeric conversions into separate `cast()` implementations to avoid the issue.
This commit is contained in:
parent
534b756cb3
commit
221fb1e11e
@ -17,6 +17,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#if defined(PYBIND11_CPP17)
|
#if defined(PYBIND11_CPP17)
|
||||||
# if defined(__has_include)
|
# if defined(__has_include)
|
||||||
@ -1009,21 +1010,34 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static handle cast(T src, return_value_policy /* policy */, handle /* parent */) {
|
template<typename U = T>
|
||||||
if (std::is_floating_point<T>::value) {
|
static typename std::enable_if<std::is_floating_point<U>::value, handle>::type
|
||||||
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
return PyFloat_FromDouble((double) src);
|
return PyFloat_FromDouble((double) src);
|
||||||
} else if (sizeof(T) <= sizeof(ssize_t)) {
|
|
||||||
// This returns a long automatically if needed
|
|
||||||
if (std::is_signed<T>::value)
|
|
||||||
return PYBIND11_LONG_FROM_SIGNED(src);
|
|
||||||
else
|
|
||||||
return PYBIND11_LONG_FROM_UNSIGNED(src);
|
|
||||||
} else {
|
|
||||||
if (std::is_signed<T>::value)
|
|
||||||
return PyLong_FromLongLong((long long) src);
|
|
||||||
else
|
|
||||||
return PyLong_FromUnsignedLongLong((unsigned long long) src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename U = T>
|
||||||
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_signed<U>::value && (sizeof(U) <= sizeof(long)), handle>::type
|
||||||
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PYBIND11_LONG_FROM_SIGNED((long) src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U = T>
|
||||||
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_unsigned<U>::value && (sizeof(U) <= sizeof(unsigned long)), handle>::type
|
||||||
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PYBIND11_LONG_FROM_UNSIGNED((unsigned long) src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U = T>
|
||||||
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_signed<U>::value && (sizeof(U) > sizeof(long)), handle>::type
|
||||||
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PyLong_FromLongLong((long long) src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U = T>
|
||||||
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_unsigned<U>::value && (sizeof(U) > sizeof(unsigned long)), handle>::type
|
||||||
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PyLong_FromUnsignedLongLong((unsigned long long) src);
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
|
PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
|
||||||
|
Loading…
Reference in New Issue
Block a user