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>...) {}
struct LastElement : std::decay<decltype(
LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
};
+#endif
} // namespace detail
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.
*/