Don't make copies of std::string or fbstring when converting.
authorAndrew Krieger <andrew.krieger@oculus.com>
Tue, 17 Oct 2017 16:17:30 +0000 (09:17 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 17 Oct 2017 16:29:51 +0000 (09:29 -0700)
Summary:
This overload of estimateSpaceNeeded was taking a Src by
value, but Src is constrained by IsSomeString which only returns
true for std::string or fbstring, so this was inducing a copy
in any situation where folly::to<> is used with varargs which
contain fb/string arguments.

Reviewed By: yfeldblum

Differential Revision: D6059517

fbshipit-source-id: adc239f9049e161fc4b750bae0e3de5dbdcd1bfc

folly/Conv.h

index ce30765c6f8d3bac9e8da6129d2ba6601eaeeed9..ff3bb81d7743cc24b5aaa0c157ac141b371abe96 100644 (file)
@@ -440,12 +440,18 @@ typename std::enable_if<std::is_convertible<Src, const char*>::value, size_t>::
   return 0;
 }
 
+template <class Src>
+typename std::enable_if<IsSomeString<Src>::value, size_t>::type
+estimateSpaceNeeded(Src const& value) {
+  return value.size();
+}
+
 template <class Src>
 typename std::enable_if<
-  (std::is_convertible<Src, folly::StringPiece>::value ||
-  IsSomeString<Src>::value) &&
-  !std::is_convertible<Src, const char*>::value,
-  size_t>::type
+    std::is_convertible<Src, folly::StringPiece>::value &&
+        !IsSomeString<Src>::value &&
+        !std::is_convertible<Src, const char*>::value,
+    size_t>::type
 estimateSpaceNeeded(Src value) {
   return folly::StringPiece(value).size();
 }
@@ -1480,6 +1486,14 @@ tryTo(StringPiece src) {
   });
 }
 
+template <class Tgt, class Src>
+inline typename std::enable_if<
+    IsSomeString<Src>::value && !std::is_same<StringPiece, Tgt>::value,
+    Tgt>::type
+to(Src const& src) {
+  return to<Tgt>(StringPiece(src.data(), src.size()));
+}
+
 template <class Tgt>
 inline
     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
@@ -1557,8 +1571,10 @@ to(const Src& value) {
 
 template <class Tgt, class Src>
 typename std::enable_if<
-  std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
-to(const Src & value) {
+    !IsSomeString<Src>::value && std::is_enum<Tgt>::value &&
+        !std::is_same<Src, Tgt>::value,
+    Tgt>::type
+to(const Src& value) {
   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
 }