From 56e86ed094024eacf50aaabcfb0baa3bb182585f Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 4 Sep 2016 21:30:08 +0200 Subject: [PATCH] Workaround for py::dict() constructor on MSVC MSVC fails to compile if the constructor is defined out-of-line. The error states that it cannot deduce the type of the default template parameter which is used for SFINAE. --- include/pybind11/cast.h | 4 ---- include/pybind11/common.h | 4 ++++ include/pybind11/pytypes.h | 13 +++++++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index de185c27..144d2dc4 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1134,10 +1134,6 @@ template (std::forward(args)...); } -template -dict::dict(Args &&...args) - : dict(detail::unpacking_collector<>(std::forward(args)...).kwargs()) { } - #define PYBIND11_MAKE_OPAQUE(Type) \ namespace pybind11 { namespace detail { \ template<> class type_caster : public type_caster_base { }; \ diff --git a/include/pybind11/common.h b/include/pybind11/common.h index 88f09019..3d5aeb22 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -358,6 +358,10 @@ template class P, typename T, typename... Ts> struct any_of_t : conditional_t::value, std::true_type, any_of_t> { }; #endif +/// Defer the evaluation of type T until types Us are instantiated +template struct deferred_type { using type = T; }; +template using deferred_t = typename deferred_type::type; + /// Ignore that a variable is unused in compiler warnings inline void ignore_unused(const int *) { } diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index da22bbd3..d7fda31d 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -259,6 +259,12 @@ template using is_keyword_or_ds = bool_constant< is_keyword::value || is_ds_unpacking::value >; +// Call argument collector forward declarations +template +class simple_collector; +template +class unpacking_collector; + NAMESPACE_END(detail) #define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, CvtStmt) \ @@ -588,8 +594,11 @@ public: if (!m_ptr) pybind11_fail("Could not allocate dict object!"); } template ::value>> - dict(Args &&...args); + typename = detail::enable_if_t::value>, + // MSVC workaround: it can't compile an out-of-line definition, so defer the collector + typename collector = detail::deferred_t, Args...>> + dict(Args &&...args) : dict(collector(std::forward(args)...).kwargs()) { } + size_t size() const { return (size_t) PyDict_Size(m_ptr); } detail::dict_iterator begin() const { return (++detail::dict_iterator(*this, 0)); } detail::dict_iterator end() const { return detail::dict_iterator(); }