From df66f27a0187ee56cc5a56d425ba592425de6c39 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Mon, 15 Aug 2016 11:17:38 -0700 Subject: [PATCH] Add a pair of overloads to dynamic::setDefault Summary: This is a workaround to an (already reported) bug in MSVC that results in it not considering the constructors of `dynamic` when attempting to construct the default value of a parameter if the type of the parameter is a universal reference. It works by simply adding a pair of template specializations that cause MSVC to properly construct the default value. This also removes the default value on the universal reference version, as the only things that should be using that overload now are non-dynamic values. Reviewed By: yfeldblum Differential Revision: D3704990 fbshipit-source-id: 7b85c4e48a1a1023bc2fe0a76a9632b11c4e9364 --- folly/dynamic-inl.h | 11 +++++++++++ folly/dynamic.h | 12 ++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/folly/dynamic-inl.h b/folly/dynamic-inl.h index 08374f7b..ae484217 100644 --- a/folly/dynamic-inl.h +++ b/folly/dynamic-inl.h @@ -530,6 +530,17 @@ template inline dynamic& dynamic::setDefault(K&& k, V&& v) { std::forward(v))).first->second; } +template inline dynamic& dynamic::setDefault(K&& k, dynamic&& v) { + auto& obj = get(); + return obj.insert(std::make_pair(std::forward(k), + std::move(v))).first->second; +} + +template inline dynamic& dynamic::setDefault(K&& k, const dynamic& v) { + auto& obj = get(); + return obj.insert(std::make_pair(std::forward(k), v)).first->second; +} + inline dynamic* dynamic::get_ptr(dynamic const& idx) & { return const_cast(const_cast(this)->get_ptr(idx)); } diff --git a/folly/dynamic.h b/folly/dynamic.h index cc75cdfa..19b0c2b0 100644 --- a/folly/dynamic.h +++ b/folly/dynamic.h @@ -429,8 +429,16 @@ public: dynamic getDefault(const dynamic& k, dynamic&& v) const&; dynamic getDefault(const dynamic& k, const dynamic& v = dynamic::object) &&; dynamic getDefault(const dynamic& k, dynamic&& v) &&; - template - dynamic& setDefault(K&& k, V&& v = dynamic::object); + template + dynamic& setDefault(K&& k, V&& v); + // MSVC 2015 Update 3 needs these extra overloads because if V were a + // defaulted template parameter, it causes MSVC to consider v an rvalue + // reference rather than a universal reference, resulting in it not being + // able to find the correct overload to construct a dynamic with. + template + dynamic& setDefault(K&& k, dynamic&& v); + template + dynamic& setDefault(K&& k, const dynamic& v = dynamic::object); /* * Resizes an array so it has at n elements, using the supplied -- 2.34.1