toAppendDelimited, toDelimited
[folly.git] / folly / Conv.h
index c8360a6d7675b21f1506404c372cde0cd77eb10c..4d14a559ef92804ee626e4f71dfabefc27def8fb 100644 (file)
@@ -476,6 +476,38 @@ typename std::enable_if<detail::IsSomeString<Tgt>::value>::type
 toAppend(Tgt* result) {
 }
 
+/**
+ * Variadic base case: do nothing.
+ */
+template <class Delimiter, class Tgt>
+typename std::enable_if<detail::IsSomeString<Tgt>::value>::type
+toAppendDelim(const Delimiter& delim, Tgt* result) {
+}
+
+/**
+ * 1 element: same as toAppend.
+ */
+template <class Delimiter, class T, class Tgt>
+typename std::enable_if<detail::IsSomeString<Tgt>::value>::type
+toAppendDelim(const Delimiter& delim, const T& v, Tgt* tgt) {
+  toAppend(v, tgt);
+}
+
+/**
+ * Append to string with a delimiter in between elements.
+ */
+template <class Delimiter, class T, class... Ts>
+typename std::enable_if<sizeof...(Ts) >= 2
+  && detail::IsSomeString<
+  typename std::remove_pointer<
+    typename std::tuple_element<
+      sizeof...(Ts) - 1, std::tuple<Ts...>
+      >::type>::type>::value>::type
+toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) {
+  toAppend(v, delim, detail::getLastElement(vs...));
+  toAppendDelim(delim, vs...);
+}
+
 /**
  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
  * for all types.
@@ -488,6 +520,18 @@ to(const Ts&... vs) {
   return result;
 }
 
+/**
+ * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
+ * back-end for all types.
+ */
+template <class Tgt, class Delim, class... Ts>
+typename std::enable_if<detail::IsSomeString<Tgt>::value, Tgt>::type
+toDelim(const Delim& delim, const Ts&... vs) {
+  Tgt result;
+  toAppendDelim(delim, vs..., &result);
+  return result;
+}
+
 /*******************************************************************************
  * Conversions from string types to integral types.
  ******************************************************************************/