diff --git a/format.h b/format.h index ca1ca9e6..5bfa8f99 100644 --- a/format.h +++ b/format.h @@ -139,6 +139,10 @@ namespace fmt { FMT_GCC_EXTENSION typedef long long LongLong; FMT_GCC_EXTENSION typedef unsigned long long ULongLong; +#if FMT_USE_RVALUE_REFERENCES +using std::move; +#endif + template class BasicWriter; @@ -156,11 +160,12 @@ struct FormatSpec; or as a result of a formatting operation. It is most useful as a parameter type to allow passing different types of strings in a function, for example:: - Formatter<> Format(StringRef format); + template + Writer format(StringRef format, const Args & ... args); - Format("{}") << 42; - Format(std::string("{}")) << 42; - Format(Format("{{}}")) << 42; + format("{}", 42); + format(std::string("{}"), 42); + format(format("{{}}"), 42); \endrst */ template @@ -250,8 +255,14 @@ class Array { if (ptr_ != data_) delete [] ptr_; } + FMT_DISALLOW_COPY_AND_ASSIGN(Array); + + public: + Array() : size_(0), capacity_(SIZE), ptr_(data_) {} + ~Array() { Free(); } + // Move data from other to this array. - void Move(Array &other) { + void move(Array &other) { size_ = other.size_; capacity_ = other.capacity_; if (other.ptr_ == other.data_) { @@ -265,21 +276,15 @@ class Array { } } - FMT_DISALLOW_COPY_AND_ASSIGN(Array); - - public: - Array() : size_(0), capacity_(SIZE), ptr_(data_) {} - ~Array() { Free(); } - #if FMT_USE_RVALUE_REFERENCES Array(Array &&other) { - Move(other); + move(other); } Array& operator=(Array &&other) { assert(this != &other); Free(); - Move(other); + move(other); return *this; } #endif @@ -977,7 +982,8 @@ template class BasicWriter { private: // Output buffer. - mutable internal::Array buffer_; + typedef internal::Array Buffer; + mutable Buffer buffer_; // Make BasicFormatter a friend so that it can access ArgInfo and Arg. friend class BasicFormatter; @@ -1220,6 +1226,21 @@ class BasicWriter { buffer_ = std::move(other.buffer_); return *this; } +#else + friend inline BasicWriter &move(BasicWriter &w) { return w; } + + private: + struct Proxy { Buffer *buffer; }; + + public: + operator Proxy() { + Proxy p = {&buffer_}; + return p; + } + + // "Move" constructors. + BasicWriter(BasicWriter &other) { buffer_.move(other.buffer_); } + BasicWriter(Proxy p) { buffer_.move(*p.buffer); } #endif /** @@ -1988,25 +2009,12 @@ inline Formatter PrintColored(Color c, StringRef format) { return f; } -#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES - -template -template -void BasicWriter::Format( - BasicStringRef format, const Args & ... args) { - this->format(format, args...); -} - /** \rst Formats a string similarly to Python's `str.format `__ function and returns an :cpp:class:`fmt::BasicWriter` object containing the output. - This version of the Format function uses C++11 features such as - variadic templates and rvalue references. For C++98 version, see - the :cpp:func:`fmt::Format()` overload above. - *format* is a format string that contains literal text and replacement fields surrounded by braces ``{}``. The formatter object replaces the fields with formatted arguments and stores the output in a memory buffer. @@ -2016,11 +2024,30 @@ void BasicWriter::Format( **Example**:: - std::string message = str(Format("The answer is {}", 42)); + std::string message = str(format("The answer is {}", 42)); See also `Format String Syntax`_. \endrst - */ +*/ +inline Writer format(StringRef format, const ArgList &args) { + Writer w; + w.format(format, args); + return move(w); +} + +#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES + +template +template +void BasicWriter::Format( + BasicStringRef format, const Args & ... args) { + this->format(format, args...); +} + +// This function is deprecated, use fmt::format instead. +template +FMT_DEPRECATED(Writer Format(StringRef format, const Args & ... args)); + template inline Writer Format(StringRef format, const Args & ... args) { Writer w; @@ -2038,7 +2065,7 @@ inline WWriter Format(WStringRef format, const Args & ... args) { template void Print(StringRef format, const Args & ... args) { Writer w; - w.Format(format, args...); + w.format(format, args...); std::fwrite(w.data(), 1, w.size(), stdout); } @@ -2252,6 +2279,8 @@ inline void FormatDec(char *&buffer, T value) { #endif // FMT_USE_VARIADIC_TEMPLATES +FMT_VARIADIC(fmt::Writer, format, fmt::StringRef) + // Restore warnings. #if FMT_GCC_VERSION >= 406 # pragma GCC diagnostic pop diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a17cdb9e..424f0bae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,7 +26,7 @@ expect_compile_error("fmt::internal::Array a, b(a);") expect_compile_error("fmt::internal::Array a, b; b = a;") # Writer is noncopyable. -expect_compile_error("fmt::Writer a, b(a);") +expect_compile_error("const fmt::Writer a, b(a);") expect_compile_error("fmt::Writer a, b; b = a;") # Formatter is not copyable from a temporary. diff --git a/test/format-test.cc b/test/format-test.cc index 40b94749..a2cc90e0 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1359,9 +1359,9 @@ TEST(FormatterTest, FormatExamples) { std::string message = str(Format("The answer is {}") << 42); EXPECT_EQ("The answer is 42", message); - EXPECT_EQ("42", str(Format("{}") << 42)); - EXPECT_EQ("42", str(Format(std::string("{}")) << 42)); - EXPECT_EQ("42", str(Format(Format("{{}}")) << 42)); + EXPECT_EQ("42", str(format("{}", 42))); + EXPECT_EQ("42", str(format(std::string("{}"), 42))); + EXPECT_EQ("42", str(format(Format("{{}}"), 42))); Writer writer; writer.Format("Current point:\n"); @@ -1565,17 +1565,15 @@ TEST(FormatterTest, Examples) { std::string path = "somefile"; ReportError("File not found: {0}") << path; -#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES - EXPECT_EQ("The answer is 42", str(Format("The answer is {}", 42))); + EXPECT_EQ("The answer is 42", str(format("The answer is {}", 42))); EXPECT_THROW_MSG( - Format("The answer is {:d}", "forty-two"), FormatError, + format("The answer is {:d}", "forty-two"), FormatError, "unknown format code 'd' for string"); EXPECT_EQ(L"Cyrillic letter \x42e", str(Format(L"Cyrillic letter {}", L'\x42e'))); EXPECT_WRITE(stdout, fmt::Print("{}", std::numeric_limits::infinity()), "inf"); -#endif } TEST(FormatIntTest, Data) { @@ -1644,12 +1642,10 @@ TEST(FormatTest, PrintColored) { #endif -#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES TEST(FormatTest, Variadic) { - EXPECT_EQ("abc1", str(Format("{}c{}", "ab", 1))); + EXPECT_EQ("abc1", str(format("{}c{}", "ab", 1))); EXPECT_EQ(L"abc1", str(Format(L"{}c{}", L"ab", 1))); } -#endif // FMT_USE_VARIADIC_TEMPLATES template std::string str(const T &value) {