AsyncSSLSocket getRawBytes fix
[folly.git] / folly / Conv.h
index 9fc196965763bfddcfb997c1f1e4b781abd2637c..468d33cb08a74d467b9ed9366499f30aa87dc88e 100644 (file)
@@ -187,6 +187,33 @@ to(const Src& value) {
 
 namespace detail {
 
+#ifdef _MSC_VER
+// MSVC can't quite figure out the LastElementImpl::call() stuff
+// in the base implementation, so we have to use tuples instead,
+// which result in significantly more templates being compiled,
+// though the runtime performance is the same.
+
+template <typename... Ts>
+auto getLastElement(Ts&&... ts) -> decltype(
+    std::get<sizeof...(Ts)-1>(std::forward_as_tuple(std::forward<Ts>(ts)...))) {
+  return std::get<sizeof...(Ts)-1>(
+      std::forward_as_tuple(std::forward<Ts>(ts)...));
+}
+
+inline void getLastElement() {}
+
+template <size_t size, typename... Ts>
+struct LastElementType : std::tuple_element<size - 1, std::tuple<Ts...>> {};
+
+template <>
+struct LastElementType<0> {
+  using type = void;
+};
+
+template <class... Ts>
+struct LastElement
+    : std::decay<typename LastElementType<sizeof...(Ts), Ts...>::type> {};
+#else
 template <typename... Ts>
 struct LastElementImpl {
   static void call(Ignored<Ts>...) {}
@@ -210,6 +237,7 @@ template <class... Ts>
 struct LastElement : std::decay<decltype(
                          LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
 };
+#endif
 
 } // namespace detail
 
@@ -928,6 +956,27 @@ to(const Ts&... vs) {
   return result;
 }
 
+/**
+ * Special version of to<SomeString> for floating point. When calling
+ * folly::to<SomeString>(double), generic implementation above will
+ * firstly reserve 24 (or 25 when negative value) bytes. This will
+ * introduce a malloc call for most mainstream string implementations.
+ *
+ * But for most cases, a floating point doesn't need 24 (or 25) bytes to
+ * be converted as a string.
+ *
+ * This special version will not do string reserve.
+ */
+template <class Tgt, class Src>
+typename std::enable_if<
+    IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
+    Tgt>::type
+to(Src value) {
+  Tgt result;
+  toAppend(value, &result);
+  return result;
+}
+
 /**
  * toDelim<SomeString>(SomeString str) returns itself.
  */