const Tuple& val_;
};
+// Partial specialization of FormatValue for nested Formatters
+template <bool containerMode, class... Args>
+class FormatValue<Formatter<containerMode, Args...>, void> {
+ typedef Formatter<containerMode, Args...> FormatterValue;
+ public:
+ explicit FormatValue(const FormatterValue& f) : f_(f) { }
+
+ template <class FormatCallback>
+ void format(FormatArg& arg, FormatCallback& cb) const {
+ format_value::formatFormatter(f_, arg, cb);
+ }
+ private:
+ const FormatterValue& f_;
+};
+
/**
* Formatter objects can be appended to strings, and therefore they're
* compatible with folly::toAppend and folly::to.
}
}
+BENCHMARK_DRAW_LINE()
+
+BENCHMARK(format_nested_strings, iters) {
+ while (iters--) {
+ fbstring out;
+ for (int i = 0; i < 1000; ++i) {
+ out.clear();
+ format(&out, "{} {}",
+ format("{} {}", i, i + 1).str(),
+ format("{} {}", -i, -i - 1).str());
+ }
+ }
+}
+
+BENCHMARK_RELATIVE(format_nested_fbstrings, iters) {
+ while (iters--) {
+ fbstring out;
+ for (int i = 0; i < 1000; ++i) {
+ out.clear();
+ format(&out, "{} {}",
+ format("{} {}", i, i + 1).fbstr(),
+ format("{} {}", -i, -i - 1).fbstr());
+ }
+ }
+}
+
+BENCHMARK_RELATIVE(format_nested_direct, iters) {
+ while (iters--) {
+ fbstring out;
+ for (int i = 0; i < 1000; ++i) {
+ out.clear();
+ format(&out, "{} {}",
+ format("{} {}", i, i + 1),
+ format("{} {}", -i, -i - 1));
+ }
+ }
+}
+
// Benchmark results on my dev server (dual-CPU Xeon L5520 @ 2.7GHz)
//
// ============================================================================
EXPECT_EQ("XX<key=hello, value=42>", fstr("{:X>23}", kv));
}
+TEST(Format, Nested) {
+ EXPECT_EQ("1 2 3 4", fstr("{} {} {}", 1, 2, format("{} {}", 3, 4)));
+ //
+ // not copyable, must hold temporary in scope instead.
+ auto&& saved = format("{} {}", 3, 4);
+ EXPECT_EQ("1 2 3 4", fstr("{} {} {}", 1, 2, saved));
+}
+
int main(int argc, char *argv[]) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);