Add a pair of overloads to dynamic::setDefault
authorChristopher Dykes <cdykes@fb.com>
Mon, 15 Aug 2016 18:17:38 +0000 (11:17 -0700)
committerFacebook Github Bot 2 <facebook-github-bot-2-bot@fb.com>
Mon, 15 Aug 2016 18:23:25 +0000 (11:23 -0700)
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
folly/dynamic.h

index 08374f7bc161883e4a43380dbec748ebfe0f8492..ae48421723519649dbc74bf7e1c20ee42e09df84 100644 (file)
@@ -530,6 +530,17 @@ template<class K, class V> inline dynamic& dynamic::setDefault(K&& k, V&& v) {
                                    std::forward<V>(v))).first->second;
 }
 
+template<class K> inline dynamic& dynamic::setDefault(K&& k, dynamic&& v) {
+  auto& obj = get<ObjectImpl>();
+  return obj.insert(std::make_pair(std::forward<K>(k),
+                                   std::move(v))).first->second;
+}
+
+template<class K> inline dynamic& dynamic::setDefault(K&& k, const dynamic& v) {
+  auto& obj = get<ObjectImpl>();
+  return obj.insert(std::make_pair(std::forward<K>(k), v)).first->second;
+}
+
 inline dynamic* dynamic::get_ptr(dynamic const& idx) & {
   return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx));
 }
index cc75cdfaf9c6dd88bafde4e2faca17aa300fd771..19b0c2b05470e98ad900673ef4e61231bb7f73c5 100644 (file)
@@ -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<class K, class V = dynamic>
-  dynamic& setDefault(K&& k, V&& v = dynamic::object);
+  template<class K, class V>
+  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<class K>
+  dynamic& setDefault(K&& k, dynamic&& v);
+  template<class K>
+  dynamic& setDefault(K&& k, const dynamic& v = dynamic::object);
 
   /*
    * Resizes an array so it has at n elements, using the supplied