From 383a8423efbfc53e0b0348df4a27c715c502181a Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 4 Dec 2013 22:22:25 -0800 Subject: [PATCH] Forbid copying from a temporary (Basic)Formatter object. --- format.h | 55 ++++++++++++++++++++++---------------------------- format_test.cc | 2 +- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/format.h b/format.h index 3220c095..af3e4231 100644 --- a/format.h +++ b/format.h @@ -774,7 +774,8 @@ BasicWriter &BasicWriter::operator<<( template BasicFormatter BasicWriter::Format(StringRef format) { - return BasicFormatter(*this, format.c_str()); + BasicFormatter f(*this, format.c_str()); + return f; } typedef BasicWriter Writer; @@ -936,8 +937,12 @@ class BasicFormatter { friend class internal::FormatterProxy; - // Forbid copying other than from a temporary. Do not implement. - BasicFormatter(BasicFormatter &); + // Forbid copying from a temporary as in the following example: + // fmt::Formatter<> f = Format("test"); // not allowed + // This is done because BasicFormatter objects should normally exist + // only as temporaries returned by one of the formatting functions. + // Do not implement. + BasicFormatter(const BasicFormatter &); BasicFormatter& operator=(const BasicFormatter &); void Add(const Arg &arg) { @@ -988,13 +993,8 @@ class BasicFormatter { CompleteFormatting(); } - // Constructs a formatter from a proxy object. - BasicFormatter(const Proxy &p) : writer_(p.writer), format_(p.format) {} - - operator Proxy() { - const Char *format = format_; - format_ = 0; - return Proxy(writer_, format); + BasicFormatter(BasicFormatter &f) : writer_(f.writer_), format_(f.format_) { + f.format_ = 0; } // Feeds an argument to a formatter. @@ -1089,7 +1089,7 @@ class NoAction { // Formats an error message and prints it to stdout. fmt::Formatter ReportError(const char *format) { - return fmt::Formatter(format); + return Move(fmt::Formatter(format)); } ReportError("File not found: {}") << path; @@ -1102,16 +1102,9 @@ class Formatter : private Action, public BasicFormatter { bool inactive_; // Forbid copying other than from a temporary. Do not implement. - Formatter(Formatter &); + Formatter(const Formatter &); Formatter& operator=(const Formatter &); - struct Proxy { - const Char *format; - Action action; - - Proxy(const Char *fmt, Action a) : format(fmt), action(a) {} - }; - public: /** \rst @@ -1127,10 +1120,10 @@ class Formatter : private Action, public BasicFormatter { inactive_(false) { } - // Constructs a formatter from a proxy object. - Formatter(const Proxy &p) - : Action(p.action), BasicFormatter(writer_, p.format), + Formatter(Formatter &f) + : Action(f), BasicFormatter(writer_, f.TakeFormatString()), inactive_(false) { + f.inactive_ = true; } /** @@ -1142,14 +1135,14 @@ class Formatter : private Action, public BasicFormatter { (*this)(writer_); } } - - // Converts the formatter into a proxy object. - operator Proxy() { - inactive_ = true; - return Proxy(this->TakeFormatString(), *this); - } }; +// Removes a const qualifier from a formatter object making it moveable. +template +Formatter &Move(const Formatter &f) { + return const_cast &>(f); +} + /** Fast integer formatter. */ @@ -1223,11 +1216,11 @@ class FormatInt { \endrst */ inline Formatter<> Format(StringRef format) { - return Formatter<>(format); + return Move(Formatter<>(format)); } inline Formatter Format(WStringRef format) { - return Formatter(format); + return Move(Formatter(format)); } /** A formatting action that writes formatted output to stdout. */ @@ -1243,7 +1236,7 @@ class Write { // Example: // Print("Elapsed time: {0:.2f} seconds") << 1.23; inline Formatter Print(StringRef format) { - return Formatter(format); + return Move(Formatter(format)); } } diff --git a/format_test.cc b/format_test.cc index bd457ee5..146a2df6 100644 --- a/format_test.cc +++ b/format_test.cc @@ -1327,7 +1327,7 @@ struct PrintError { }; fmt::Formatter ReportError(const char *format) { - return fmt::Formatter(format); + return Move(fmt::Formatter(format)); } TEST(FormatterTest, Examples) {