toAppendDelim(delim, vs...);
}
+/**
+ * to<SomeString>(SomeString str) returns itself. As both std::string and
+ * folly::fbstring use Copy-on-Write, it's much more efficient by
+ * avoiding copying the underlying char array.
+ */
+template <class Tgt, class Src>
+typename std::enable_if<
+ IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
+ Tgt>::type
+to(const Src & value) {
+ return value;
+}
+
/**
* to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
* for all types.
*/
template <class Tgt, class... Ts>
-typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
+typename std::enable_if<
+ IsSomeString<Tgt>::value && (
+ sizeof...(Ts) != 1 ||
+ !std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
+ Tgt>::type
to(const Ts&... vs) {
Tgt result;
toAppend(vs..., &result);
return result;
}
+/**
+ * toDelim<SomeString>(SomeString str) returns itself.
+ */
+template <class Tgt, class Delim, class Src>
+typename std::enable_if<
+ IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
+ Tgt>::type
+toDelim(const Delim& delim, const Src & value) {
+ return value;
+}
+
/**
* toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
* back-end for all types.
*/
template <class Tgt, class Delim, class... Ts>
-typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
+typename std::enable_if<
+ IsSomeString<Tgt>::value && (
+ sizeof...(Ts) != 1 ||
+ !std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
+ Tgt>::type
toDelim(const Delim& delim, const Ts&... vs) {
Tgt result;
toAppendDelim(delim, vs..., &result);
}
}
+template <class String>
+void testIdenticalTo() {
+ String s("Yukkuri shiteitte ne!!!");
+
+ String result = to<String>(s);
+ EXPECT_EQ(result, s);
+}
+
template <class String>
void testVariadicTo() {
String s;
EXPECT_EQ(s, "Lorem ipsum 1234 dolor amet 567.89.");
}
+template <class String>
+void testIdenticalToDelim() {
+ String s("Yukkuri shiteitte ne!!!");
+
+ String charDelim = toDelim<String>('$', s);
+ EXPECT_EQ(charDelim, s);
+
+ String strDelim = toDelim<String>(String(">_<"), s);
+ EXPECT_EQ(strDelim, s);
+}
+
template <class String>
void testVariadicToDelim() {
String s;
}
TEST(Conv, VariadicTo) {
+ testIdenticalTo<string>();
+ testIdenticalTo<fbstring>();
testVariadicTo<string>();
testVariadicTo<fbstring>();
}
TEST(Conv, VariadicToDelim) {
+ testIdenticalToDelim<string>();
+ testIdenticalToDelim<fbstring>();
testVariadicToDelim<string>();
testVariadicToDelim<fbstring>();
}
}
}
+template <class String>
+struct StringIdenticalToBM {
+ void operator()(unsigned int n, size_t len) const {
+ String s;
+ BENCHMARK_SUSPEND { s.append(len, '0'); }
+ FOR_EACH_RANGE (i, 0, n) {
+ String result = to<String>(s);
+ doNotOptimizeAway(result.size());
+ }
+ }
+};
+
+template <class String>
+struct StringVariadicToBM {
+ void operator()(unsigned int n, size_t len) const {
+ String s;
+ BENCHMARK_SUSPEND { s.append(len, '0'); }
+ FOR_EACH_RANGE (i, 0, n) {
+ String result = to<String>(s, nullptr);
+ doNotOptimizeAway(result.size());
+ }
+ }
+};
+
+static const StringIdenticalToBM<std::string> stringIdenticalToBM;
+static const StringVariadicToBM<std::string> stringVariadicToBM;
+static const StringIdenticalToBM<fbstring> fbstringIdenticalToBM;
+static const StringVariadicToBM<fbstring> fbstringVariadicToBM;
+
#define DEFINE_BENCHMARK_GROUP(n) \
BENCHMARK_PARAM(u64ToAsciiClassicBM, n); \
BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM, n); \
#undef DEFINE_BENCHMARK_GROUP
+#define DEFINE_BENCHMARK_GROUP(T, n) \
+ BENCHMARK_PARAM(T ## VariadicToBM, n); \
+ BENCHMARK_RELATIVE_PARAM(T ## IdenticalToBM, n); \
+ BENCHMARK_DRAW_LINE();
+
+DEFINE_BENCHMARK_GROUP(string, 32);
+DEFINE_BENCHMARK_GROUP(string, 1024);
+DEFINE_BENCHMARK_GROUP(string, 32768);
+DEFINE_BENCHMARK_GROUP(fbstring, 32);
+DEFINE_BENCHMARK_GROUP(fbstring, 1024);
+DEFINE_BENCHMARK_GROUP(fbstring, 32768);
+
+#undef DEFINE_BENCHMARK_GROUP
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);