@@ -225,6 +225,7 @@ using cast_op_type = typename std::conditional<std::is_pointer<typename std::rem
225225 typename std::add_pointer<typename intrinsic_type<T>::type>::type,
226226 typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type;
227227
228+
228229// / Generic type caster for objects stored on the heap
229230template <typename type> class type_caster_base : public type_caster_generic {
230231public:
@@ -247,22 +248,35 @@ template <typename type> class type_caster_base : public type_caster_generic {
247248 static handle cast (const type *src, return_value_policy policy, handle parent) {
248249 return type_caster_generic::cast (
249250 src, policy, parent, src ? &typeid (*src) : nullptr , &typeid (type),
250- ©_constructor, &move_constructor );
251+ make_copy_constructor (src), make_move_constructor (src) );
251252 }
252253
253254 template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
254255
255256 operator type*() { return (type *) value; }
256257 operator type&() { return *((type *) value); }
258+
257259protected:
258- template <typename T = type, typename std::enable_if<detail::is_copy_constructible<T>::value, int >::type = 0 >
259- static void *copy_constructor (const void *arg) { return (void *) new type (*((const type *) arg)); }
260- template <typename T = type, typename std::enable_if<!detail::is_copy_constructible<T>::value, int >::type = 0 >
261- static void *copy_constructor (const void *) { return nullptr ; }
262- template <typename T = type, typename std::enable_if<detail::is_move_constructible<T>::value, int >::type = 0 >
263- static void *move_constructor (const void *arg) { return (void *) new type (std::move (*((type *) arg))); }
264- template <typename T = type, typename std::enable_if<!detail::is_move_constructible<T>::value, int >::type = 0 >
265- static void *move_constructor (const void *) { return nullptr ; }
260+ typedef void *(*Constructor)(const void *stream);
261+ #if !defined(_MSC_VER)
262+ /* Only enabled when the types are {copy,move}-constructible *and* when the type
263+ does not have a private operator new implementaton. */
264+ template <typename T = type> static auto make_copy_constructor (const T *value) -> decltype(new T(*value), Constructor(nullptr )) {
265+ return [](const void *arg) -> void * { return new T (*((const T *) arg)); }; }
266+ template <typename T = type> static auto make_move_constructor (const T *value) -> decltype(new T(std::move(*((T *) value))), Constructor(nullptr )) {
267+ return [](const void *arg) -> void * { return (void *) new T (std::move (*((T *) arg))); }; }
268+ #else
269+ /* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations.
270+ Use a workaround that only tests for constructibility for now. */
271+ template <typename T = type, typename = typename std::enable_if<std::is_copy_constructible<T>::value>::type>
272+ static Constructor make_copy_constructor (const T *value) {
273+ return [](const void *arg) -> void * { return new T (*((const T *)arg)); }; }
274+ template <typename T = type, typename = typename std::enable_if<std::is_move_constructible<T>::value>::type>
275+ static Constructor make_move_constructor (const T *value) {
276+ return [](const void *arg) -> void * { return (void *) new T (std::move (*((T *)arg))); }; }
277+ #endif
278+ static Constructor make_copy_constructor (...) { return nullptr ; }
279+ static Constructor make_move_constructor (...) { return nullptr ; }
266280};
267281
268282template <typename type, typename SFINAE = void > class type_caster : public type_caster_base <type> { };
0 commit comments