mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
copy/move constructor detection workaround (MSVC 2015 bug)
This commit is contained in:
parent
8e93df825e
commit
2bc946bd7a
@ -225,6 +225,7 @@ using cast_op_type = typename std::conditional<std::is_pointer<typename std::rem
|
||||
typename std::add_pointer<typename intrinsic_type<T>::type>::type,
|
||||
typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type;
|
||||
|
||||
|
||||
/// Generic type caster for objects stored on the heap
|
||||
template <typename type> class type_caster_base : public type_caster_generic {
|
||||
public:
|
||||
@ -247,22 +248,35 @@ public:
|
||||
static handle cast(const type *src, return_value_policy policy, handle parent) {
|
||||
return type_caster_generic::cast(
|
||||
src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type),
|
||||
©_constructor, &move_constructor);
|
||||
make_copy_constructor(src), make_move_constructor(src));
|
||||
}
|
||||
|
||||
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
|
||||
|
||||
operator type*() { return (type *) value; }
|
||||
operator type&() { return *((type *) value); }
|
||||
|
||||
protected:
|
||||
template <typename T = type, typename std::enable_if<detail::is_copy_constructible<T>::value, int>::type = 0>
|
||||
static void *copy_constructor(const void *arg) { return (void *) new type(*((const type *) arg)); }
|
||||
template <typename T = type, typename std::enable_if<!detail::is_copy_constructible<T>::value, int>::type = 0>
|
||||
static void *copy_constructor(const void *) { return nullptr; }
|
||||
template <typename T = type, typename std::enable_if<detail::is_move_constructible<T>::value, int>::type = 0>
|
||||
static void *move_constructor(const void *arg) { return (void *) new type(std::move(*((type *) arg))); }
|
||||
template <typename T = type, typename std::enable_if<!detail::is_move_constructible<T>::value, int>::type = 0>
|
||||
static void *move_constructor(const void *) { return nullptr; }
|
||||
typedef void *(*Constructor)(const void *stream);
|
||||
#if !defined(_MSC_VER)
|
||||
/* Only enabled when the types are {copy,move}-constructible *and* when the type
|
||||
does not have a private operator new implementaton. */
|
||||
template <typename T = type> static auto make_copy_constructor(const T *value) -> decltype(new T(*value), Constructor(nullptr)) {
|
||||
return [](const void *arg) -> void * { return new T(*((const T *) arg)); }; }
|
||||
template <typename T = type> static auto make_move_constructor(const T *value) -> decltype(new T(std::move(*((T *) value))), Constructor(nullptr)) {
|
||||
return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *) arg))); }; }
|
||||
#else
|
||||
/* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations.
|
||||
Use a workaround that only tests for constructibility for now. */
|
||||
template <typename T = type, typename = typename std::enable_if<std::is_copy_constructible<T>::value>::type>
|
||||
static Constructor make_copy_constructor(const T *value) {
|
||||
return [](const void *arg) -> void * { return new T(*((const T *)arg)); }; }
|
||||
template <typename T = type, typename = typename std::enable_if<std::is_move_constructible<T>::value>::type>
|
||||
static Constructor make_move_constructor(const T *value) {
|
||||
return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *)arg))); }; }
|
||||
#endif
|
||||
static Constructor make_copy_constructor(...) { return nullptr; }
|
||||
static Constructor make_move_constructor(...) { return nullptr; }
|
||||
};
|
||||
|
||||
template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { };
|
||||
|
@ -293,20 +293,6 @@ template <typename T> struct intrinsic_type<T&&> { typedef type
|
||||
template <typename T, size_t N> struct intrinsic_type<const T[N]> { typedef typename intrinsic_type<T>::type type; };
|
||||
template <typename T, size_t N> struct intrinsic_type<T[N]> { typedef typename intrinsic_type<T>::type type; };
|
||||
|
||||
/** \brief SFINAE helper class to check if a copy constructor is usable (in contrast to
|
||||
* std::is_copy_constructible, this class also checks if the 'new' operator is accessible */
|
||||
template <typename T> struct is_copy_constructible {
|
||||
template <typename T2> static std::true_type test(decltype(new T2(std::declval<typename std::add_lvalue_reference<T2>::type>())) *);
|
||||
template <typename T2> static std::false_type test(...);
|
||||
static const bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename T> struct is_move_constructible {
|
||||
template <typename T2> static std::true_type test(decltype(new T2(std::declval<T2>())) *);
|
||||
template <typename T2> static std::false_type test(...);
|
||||
static const bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
/// Helper type to replace 'void' in some expressions
|
||||
struct void_type { };
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user