ChangeLog-old.md 110 KB

7.1.3 - 2020-11-24

7.1.2 - 2020-11-04

7.1.1 - 2020-11-01

7.1.0 - 2020-10-25

It is possible to get even better performance at the cost of larger binary size by compiling with the FMT_USE_FULL_CACHE_DRAGONBOX macro set to 1.

Thanks @jk-jeon.

Thanks @adamburgess.

  • Added support for ranges with non-const begin/end to fmt::join (https://github.com/fmtlib/fmt/issues/1784, https://github.com/fmtlib/fmt/pull/1786). For example (godbolt):

    #include <fmt/ranges.h>
    #include <range/v3/view/filter.hpp>
    
    int main() {
    using std::literals::string_literals::operator""s;
    auto strs = std::array{"a"s, "bb"s, "ccc"s};
    auto range = strs | ranges::views::filter(
      [] (const std::string &x) { return x.size() != 2; }
    );
    fmt::print("{}\n", fmt::join(range, ""));
    }
    

prints \"accc\".

Thanks @tonyelewis.

  • Added a memory_buffer::append overload that takes a range (https://github.com/fmtlib/fmt/pull/1806). Thanks @BRevzin.

  • Improved handling of single code units in FMT_COMPILE. For example:

    #include <fmt/compile.h>
    
    char* f(char* buf) {
    return fmt::format_to(buf, FMT_COMPILE("x{}"), 42);
    }
    

compiles to just (godbolt):

  _Z1fPc:
    movb $120, (%rdi)
    xorl %edx, %edx
    cmpl $42, _ZN3fmt2v76detail10basic_dataIvE23zero_or_powers_of_10_32E+8(%rip)
    movl $3, %eax
    seta %dl
    subl %edx, %eax
    movzwl _ZN3fmt2v76detail10basic_dataIvE6digitsE+84(%rip), %edx
    cltq
    addq %rdi, %rax
    movw %dx, -2(%rax)
    ret

Here a single mov instruction writes 'x' ($120) to the output buffer.

  • Added dynamic width support to format string compilation (https://github.com/fmtlib/fmt/issues/1809).

  • Improved error reporting for unformattable types: now you\'ll get the type name directly in the error message instead of the note:

    #include <fmt/core.h>
    
    struct how_about_no {};
    
    int main() {
    fmt::print("{}", how_about_no());
    }
    

Error (godbolt):

fmt/core.h:1438:3: error: static_assert failed due to requirement 'fmt::v7::formattable<how_about_no>()' "Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt" ...

  • Added the make_args_checked function template that allows you to write formatting functions with compile-time format string checks and avoid binary code bloat (godbolt):

    void vlog(const char* file, int line, fmt::string_view format,
            fmt::format_args args) {
    fmt::print("{}: {}: ", file, line);
    fmt::vprint(format, args);
    }
    
    template <typename S, typename... Args>
    void log(const char* file, int line, const S& format, Args&&... args) {
    vlog(file, line, format,
        fmt::make_args_checked<Args...>(format, args...));
    }
    
    #define MY_LOG(format, ...) \
    log(__FILE__, __LINE__, FMT_STRING(format), __VA_ARGS__)
    
    MY_LOG("invalid squishiness: {}", 42);
    
  • Replaced snprintf fallback with a faster internal IEEE 754 float and double formatter for arbitrary precision. For example (godbolt):

    #include <fmt/core.h>
    
    int main() {
    fmt::print("{:.500}\n", 4.9406564584124654E-324);
    }
    

prints

4.9406564584124654417656879286822137236505980261432476442558568250067550727020875186529983636163599237979656469544571773092665671035593979639877479601078187812630071319031140452784581716784898210368871863605699873072305000638740915356498438731247339727316961514003171538539807412623856559117102665855668676818703956031062493194527159149245532930545654440112748012970999954193198940908041656332452475714786901472678015935523861155013480352649347201937902681071074917033322268447533357208324319360923829e-324.

Thanks @Kurkin and @alexezeder.

Thanks @Naios.

prints 0.50.

7.0.3 - 2020-08-06

7.0.2 - 2020-07-29

7.0.1 - 2020-07-07

7.0.0 - 2020-07-05

  • Reduced the library size. For example, on macOS a stripped test binary statically linked with {fmt} shrank from ~368k to less than 100k.

  • Added a simpler and more efficient format string compilation API:

    #include <fmt/compile.h>
    
    // Converts 42 into std::string using the most efficient method and no
    // runtime format string processing.
    std::string s = fmt::format(FMT_COMPILE("{}"), 42);
    

The old fmt::compile API is now deprecated.

  • Optimized integer formatting: format_to with format string compilation and a stack-allocated buffer is now faster than to_chars on both libc++ and libstdc++.

  • Optimized handling of small format strings. For example,

    fmt::format("Result: {}: ({},{},{},{})", str1, str2, str3, str4, str5)
    

is now ~40% faster (https://github.com/fmtlib/fmt/issues/1685).

  • Applied extern templates to improve compile times when using the core API and fmt/format.h (https://github.com/fmtlib/fmt/issues/1452). For example, on macOS with clang the compile time of a test translation unit dropped from 2.3s to 0.3s with -O2 and from 0.6s to 0.3s with the default settings (-O0).

Before (-O2):

  % time c++ -c test.cc -I include -std=c++17 -O2
  c++ -c test.cc -I include -std=c++17 -O2  2.22s user 0.08s system 99% cpu 2.311 total

After (-O2):

  % time c++ -c test.cc -I include -std=c++17 -O2
  c++ -c test.cc -I include -std=c++17 -O2  0.26s user 0.04s system 98% cpu 0.303 total

Before (default):

  % time c++ -c test.cc -I include -std=c++17
  c++ -c test.cc -I include -std=c++17  0.53s user 0.06s system 98% cpu 0.601 total

After (default):

  % time c++ -c test.cc -I include -std=c++17
  c++ -c test.cc -I include -std=c++17  0.24s user 0.06s system 98% cpu 0.301 total

It is still recommended to use fmt/core.h instead of fmt/format.h but the compile time difference is now smaller. Thanks @alex3d for the suggestion.

  • Named arguments are now stored on stack (no dynamic memory allocations) and the compiled code is more compact and efficient. For example

    #include <fmt/core.h>
    
    int main() {
    fmt::print("The answer is {answer}\n", fmt::arg("answer", 42));
    }
    

compiles to just (godbolt)

  .LC0:
          .string "answer"
  .LC1:
          .string "The answer is {answer}\n"
  main:
          sub     rsp, 56
          mov     edi, OFFSET FLAT:.LC1
          mov     esi, 23
          movabs  rdx, 4611686018427387905
          lea     rax, [rsp+32]
          lea     rcx, [rsp+16]
          mov     QWORD PTR [rsp+8], 1
          mov     QWORD PTR [rsp], rax
          mov     DWORD PTR [rsp+16], 42
          mov     QWORD PTR [rsp+32], OFFSET FLAT:.LC0
          mov     DWORD PTR [rsp+40], 0
          call    fmt::v6::vprint(fmt::v6::basic_string_view<char>,
                                  fmt::v6::format_args)
          xor     eax, eax
          add     rsp, 56
          ret

      .L.str.1:
              .asciz  "answer"

now gives a compilation error because argument 1 doesn\'t exist:

  In file included from test.cc:1:
  include/fmt/format.h:2726:27: error: constexpr variable 'invalid_format' must be
  initialized by a constant expression
    FMT_CONSTEXPR_DECL bool invalid_format =
                            ^
  ...
  include/fmt/core.h:569:26: note: in call to
  '&checker(s, {}).context_->on_error(&"argument not found"[0])'
      if (id >= num_args_) on_error("argument not found");
                          ^
  • Added sentinel support to fmt::join (https://github.com/fmtlib/fmt/pull/1689)

    struct zstring_sentinel {};
    bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
    bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
    
    struct zstring {
    const char* p;
    const char* begin() const { return p; }
    zstring_sentinel end() const { return {}; }
    };
    
    auto s = fmt::format("{}", fmt::join(zstring{"hello"}, "_"));
    // s == "h_e_l_l_o"
    

Thanks @BRevzin.

6.2.1 - 2020-05-09

6.2.0 - 2020-04-05

  • Improved error reporting when trying to format an object of a non-formattable type:

    fmt::format("{}", S());
    

now gives:

  include/fmt/core.h:1015:5: error: static_assert failed due to requirement
  'formattable' "Cannot format argument. To make type T formattable provide a
  formatter<T> specialization:
  https://fmt.dev/latest/api.html#formatting-user-defined-types"
      static_assert(
      ^
  ...
  note: in instantiation of function template specialization
  'fmt::v6::format<char [3], S, char>' requested here
    fmt::format("{}", S());
         ^

if S is not formattable.

now prints 42.

  • Implemented the 'L' specifier for locale-specific numeric formatting to improve compatibility with std::format. The 'n' specifier is now deprecated and will be removed in the next major release.

  • Moved OS-specific APIs such as windows_error from fmt/format.h to fmt/os.h. You can define FMT_DEPRECATED_INCLUDE_OS to automatically include fmt/os.h from fmt/format.h for compatibility but this will be disabled in the next major release.

  • Added precision overflow detection in floating-point formatting.

  • Implemented detection of invalid use of fmt::arg.

  • Used type_identity to block unnecessary template argument deduction. Thanks Tim Song.

  • Improved UTF-8 handling (https://github.com/fmtlib/fmt/issues/1109):

    fmt::print("┌{0:─^{2}}┐\n"
             "│{1: ^{2}}│\n"
             "└{0:─^{2}}┘\n", "", "Прывітанне, свет!", 21);
    

now prints:

  ┌─────────────────────┐
  │  Прывітанне, свет!  │
  └─────────────────────┘

on systems that support Unicode.

prints:

  The answer is 42.

Thanks @vsolontsov-ll.

6.1.2 - 2019-12-11

6.1.1 - 2019-12-04

6.1.0 - 2019-12-01

  • {fmt} now formats IEEE 754 float and double using the shortest decimal representation with correct rounding by default:

    #include <cmath>
    #include <fmt/core.h>
    
    int main() {
    fmt::print("{}", M_PI);
    }
    

prints 3.141592653589793.

  • Made the fast binary to decimal floating-point formatter the default, simplified it and improved performance. {fmt} is now 15 times faster than libc++\'s std::ostringstream, 11 times faster than printf and 10% faster than double-conversion on dtoa-benchmark:

| Function | Time (ns) | Speedup | | ------------- | --------: | ------: | | ostringstream | 1,346.30 | 1.00x | | ostrstream | 1,195.74 | 1.13x | | sprintf | 995.08 | 1.35x | | doubleconv | 99.10 | 13.59x | | fmt | 88.34 | 15.24x |

prints 0.1 instead of 0.10000000149011612.

Thanks @orivej.

prints 170141183460469231731687303715884105727.

Thanks @denizevrenci.

prints ('a', 1, 2.0).

Thanks @jeremyong.

  • Changed formatting of octal zero with prefix from \"00\" to \"0\":

    fmt::print("{:#o}", 0);
    

prints 0.

  • The locale is now passed to ostream insertion (<<) operators (https://github.com/fmtlib/fmt/pull/1406):

    #include <fmt/locale.h>
    #include <fmt/ostream.h>
    
    struct S {
    double value;
    };
    
    std::ostream& operator<<(std::ostream& os, S s) {
    return os << s.value;
    }
    
    int main() {
    auto s = fmt::format(std::locale("fr_FR.UTF-8"), "{}", S{0.42});
    // s == "0,42"
    }
    

Thanks @dlaugt.

Thanks @tdegeus.

6.0.0 - 2019-08-26

  • Switched to the MIT license with an optional exception that allows distributing binary code without attribution.

  • Floating-point formatting is now locale-independent by default:

    #include <locale>
    #include <fmt/core.h>
    
    int main() {
    std::locale::global(std::locale("ru_RU.UTF-8"));
    fmt::print("value = {}", 4.2);
    }
    

prints \"value = 4.2\" regardless of the locale.

For locale-specific formatting use the n specifier:

  std::locale::global(std::locale("ru_RU.UTF-8"));
  fmt::print("value = {:n}", 4.2);

prints \"value = 4,2\".

  • Added an experimental Grisu floating-point formatting algorithm implementation (disabled by default). To enable it compile with the FMT_USE_GRISU macro defined to 1:

    #define FMT_USE_GRISU 1
    #include <fmt/format.h>
    
    auto s = fmt::format("{}", 4.2); // formats 4.2 using Grisu
    

With Grisu enabled, {fmt} is 13x faster than std::ostringstream (libc++) and 10x faster than sprintf on dtoa-benchmark (full results):

It moves the cost of parsing a format string outside of the format function which can be beneficial when identically formatting many objects of the same types. Thanks @stryku.

Thanks @gawain-bolton.

Thanks @DanielaE.

  • Implemented chrono format specifiers %Q and %q that give the value and the unit respectively (https://github.com/fmtlib/fmt/pull/1019):

    auto value = fmt::format("{:%Q}", 42s); // value == "42"
    auto unit  = fmt::format("{:%q}", 42s); // unit == "s"
    

Thanks @DanielaE.

  • Fixed handling of dynamic width in chrono formatter:

    auto s = fmt::format("{0:{1}%H:%M:%S}", std::chrono::seconds(12345), 12);
    //                        ^ width argument index                     ^ width
    // s == "03:25:45    "
    

Thanks Howard Hinnant.

Thanks @Naios.

  • Removed the deprecated color API (print_colored). Use the new API, namely print overloads that take text_style instead.

  • Made std::unique_ptr and std::shared_ptr formattable as pointers via fmt::ptr (https://github.com/fmtlib/fmt/pull/1121):

    std::unique_ptr<int> p = ...;
    fmt::print("{}", fmt::ptr(p)); // prints p as a pointer
    

Thanks @sighingnow.

5.3.0 - 2018-12-28

  • Introduced experimental chrono formatting support:

    #include <fmt/chrono.h>
    
    int main() {
    using namespace std::literals::chrono_literals;
    fmt::print("Default format: {} {}\n", 42s, 100ms);
    fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
    }
    

prints:

  Default format: 42s 100ms
  strftime-like format: 03:15:30
  • Added experimental support for emphasis (bold, italic, underline, strikethrough), colored output to a file stream, and improved colored formatting API (https://github.com/fmtlib/fmt/pull/961, https://github.com/fmtlib/fmt/pull/967, https://github.com/fmtlib/fmt/pull/973):

    #include <fmt/color.h>
    
    int main() {
    fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
               "Hello, {}!\n", "world");
    fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
               fmt::emphasis::underline, "Olá, {}!\n", "Mundo");
    fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
               "你好{}!\n", "世界");
    }
    

prints the following on modern terminals with RGB color support:

Thanks @Rakete1111.

Note that these colors vary by terminal:

Thanks @Rakete1111.

Thanks @DanielaE.

Thanks @DanielaE.

Thanks @XZiar.

Thanks @DanielaE.

5.2.1 - 2018-09-21

5.2.0 - 2018-09-13

  • Optimized format string parsing and argument processing which resulted in up to 5x speed up on long format strings and significant performance boost on various benchmarks. For example, version 5.2 is 2.22x faster than 5.1 on decimal integer formatting with format_to (macOS, clang-902.0.39.2):

| Method | Time, s | Speedup | | -------------------------- | --------------: | ------: | | fmt::format 5.1 | 0.58 | | | fmt::format 5.2 | 0.35 | 1.66x | | fmt::format_to 5.1 | 0.51 | | | fmt::format_to 5.2 | 0.23 | 2.22x | | sprintf | 0.71 | | | std::to_string | 1.01 | | | std::stringstream | 1.73 | |

  • Changed the fmt macro from opt-out to opt-in to prevent name collisions. To enable it define the FMT_STRING_ALIAS macro to 1 before including fmt/format.h:

    #define FMT_STRING_ALIAS 1
    #include <fmt/format.h>
    std::string answer = format(fmt("{}"), 42);
    
  • Added compile-time format string checks to format_to overload that takes fmt::memory_buffer (https://github.com/fmtlib/fmt/issues/783):

    fmt::memory_buffer buf;
    // Compile-time error: invalid type specifier.
    fmt::format_to(buf, fmt("{:d}"), "foo");
    
  • Moved experimental color support to fmt/color.h and enabled the new API by default. The old API can be enabled by defining the FMT_DEPRECATED_COLORS macro.

  • Added formatting support for types explicitly convertible to fmt::string_view:

    struct foo {
    explicit operator fmt::string_view() const { return "foo"; }
    };
    auto s = format("{}", foo());
    

In particular, this makes formatting function work with folly::StringPiece.

5.1.0 - 2018-07-05

  • Added experimental support for RGB color output enabled with the FMT_EXTENDED_COLORS macro:

    #define FMT_EXTENDED_COLORS
    #define FMT_HEADER_ONLY // or compile fmt with FMT_EXTENDED_COLORS defined
    #include <fmt/format.h>
    
    fmt::print(fmt::color::steel_blue, "Some beautiful text");
    

The old API (the print_colored and vprint_colored functions and the color enum) is now deprecated. (https://github.com/fmtlib/fmt/issues/762 https://github.com/fmtlib/fmt/pull/767). thanks @Remotion.

5.0.0 - 2018-05-21

  • Added a requirement for partial C++11 support, most importantly variadic templates and type traits, and dropped FMT_VARIADIC_* emulation macros. Variadic templates are available since GCC 4.4, Clang 2.9 and MSVC 18.0 (2013). For older compilers use {fmt} version 4.x which continues to be maintained and works with C++98 compilers.

  • Renamed symbols to follow standard C++ naming conventions and proposed a subset of the library for standardization in P0645R2 Text Formatting.

  • Implemented constexpr parsing of format strings and compile-time format string checks. For example

    #include <fmt/format.h>
    
    std::string s = format(fmt("{:d}"), "foo");
    

gives a compile-time error because d is an invalid specifier for strings (godbolt):

  ...
  <source>:4:19: note: in instantiation of function template specialization 'fmt::v5::format<S, char [4]>' requested here
    std::string s = format(fmt("{:d}"), "foo");
                    ^
  format.h:1337:13: note: non-constexpr function 'on_error' cannot be used in a constant expression
      handler.on_error("invalid type specifier");

Compile-time checks require relaxed constexpr (C++14 feature) support. If the latter is not available, checks will be performed at runtime.

  • Separated format string parsing and formatting in the extension API to enable compile-time format string processing. For example

    struct Answer {};
    
    namespace fmt {
    template <>
    struct formatter<Answer> {
    constexpr auto parse(parse_context& ctx) {
      auto it = ctx.begin();
      spec = *it;
      if (spec != 'd' && spec != 's')
        throw format_error("invalid specifier");
      return ++it;
    }
    
    template <typename FormatContext>
    auto format(Answer, FormatContext& ctx) {
      return spec == 's' ?
        format_to(ctx.begin(), "{}", "fourty-two") :
        format_to(ctx.begin(), "{}", 42);
    }
    
    char spec = 0;
    };
    }
    
    std::string s = format(fmt("{:x}"), Answer());
    

gives a compile-time error due to invalid format specifier (godbolt):

  ...
  <source>:12:45: error: expression '<throw-expression>' is not a constant expression
         throw format_error("invalid specifier");
  • Added iterator support:

    #include <vector>
    #include <fmt/format.h>
    
    std::vector<char> out;
    fmt::format_to(std::back_inserter(out), "{}", 42);
    
  • Added the format_to_n function that restricts the output to the specified number of characters (https://github.com/fmtlib/fmt/issues/298):

    char out[4];
    fmt::format_to_n(out, sizeof(out), "{}", 12345);
    // out == "1234" (without terminating '\0')
    
  • Added the formatted_size function for computing the output size:

    #include <fmt/format.h>
    
    auto size = fmt::formatted_size("{}", 12345); // size == 5
    
  • Improved compile times by reducing dependencies on standard headers and providing a lightweight core API:

    #include <fmt/core.h>
    
    fmt::print("The answer is {}.", 42);
    

See Compile time and code bloat.

  • Added the make_format_args function for capturing formatting arguments:

    // Prints formatted error message.
    void vreport_error(const char *format, fmt::format_args args) {
    fmt::print("Error: ");
    fmt::vprint(format, args);
    }
    template <typename... Args>
    void report_error(const char *format, const Args & ... args) {
    vreport_error(format, fmt::make_format_args(args...));
    }
    
  • Added the make_printf_args function for capturing printf arguments (https://github.com/fmtlib/fmt/issues/687, https://github.com/fmtlib/fmt/pull/694). Thanks @Kronuz.

  • Added prefix v to non-variadic functions taking format_args to distinguish them from variadic ones:

    std::string vformat(string_view format_str, format_args args);
    
    template <typename... Args>
    std::string format(string_view format_str, const Args & ... args);
    
  • Added experimental support for formatting ranges, containers and tuple-like types in fmt/ranges.h (https://github.com/fmtlib/fmt/pull/735):

    #include <fmt/ranges.h>
    
    std::vector<int> v = {1, 2, 3};
    fmt::print("{}", v); // prints {1, 2, 3}
    

Thanks @Remotion.

  • Implemented wchar_t date and time formatting (https://github.com/fmtlib/fmt/pull/712):

    #include <fmt/time.h>
    
    std::time_t t = std::time(nullptr);
    auto s = fmt::format(L"The date is {:%Y-%m-%d}.", *std::localtime(&t));
    

Thanks @DanielaE.

  • Provided more wide string overloads (https://github.com/fmtlib/fmt/pull/724). Thanks @DanielaE.

  • Switched from a custom null-terminated string view class to string_view in the format API and provided fmt::string_view which implements a subset of std::string_view API for pre-C++17 systems.

  • Added support for std::experimental::string_view (https://github.com/fmtlib/fmt/pull/607):

    #include <fmt/core.h>
    #include <experimental/string_view>
    
    fmt::print("{}", std::experimental::string_view("foo"));
    

Thanks @virgiliofornazin.

4.1.0 - 2017-12-20

4.0.0 - 2017-06-27

Thanks @glebov-andrey.

Thanks @mojoBrendan, @manylegged and @spacemoose. See also https://github.com/fmtlib/fmt/issues/360, https://github.com/fmtlib/fmt/issues/335 and https://github.com/fmtlib/fmt/issues/331.

  • Added container.h containing a BasicContainerWriter to write to containers like std::vector (https://github.com/fmtlib/fmt/pull/450). Thanks @polyvertex.

  • Added fmt::join() function that takes a range and formats its elements separated by a given string (https://github.com/fmtlib/fmt/pull/466):

    #include "fmt/format.h"
    
    std::vector<double> v = {1.2, 3.4, 5.6};
    // Prints "(+01.20, +03.40, +05.60)".
    fmt::print("({:+06.2f})", fmt::join(v.begin(), v.end(), ", "));
    

Thanks @olivier80.

3.0.2 - 2017-06-14

3.0.1 - 2016-11-01

3.0.0 - 2016-05-07

  • The project has been renamed from C++ Format (cppformat) to fmt for consistency with the used namespace and macro prefix (https://github.com/fmtlib/fmt/issues/307). Library headers are now located in the fmt directory:

    #include "fmt/format.h"
    

Including format.h from the cppformat directory is deprecated but works via a proxy header which will be removed in the next major version.

The documentation is now available at https://fmt.dev.

  • Added support for strftime-like date and time formatting (https://github.com/fmtlib/fmt/issues/283):

    #include "fmt/time.h"
    
    std::time_t t = std::time(nullptr);
    // Prints "The date is 2016-04-29." (with the current date)
    fmt::print("The date is {:%Y-%m-%d}.", *std::localtime(&t));
    
  • std::ostream support including formatting of user-defined types that provide overloaded operator<< has been moved to fmt/ostream.h:

    #include "fmt/ostream.h"
    
    class Date {
    int year_, month_, day_;
    public:
    Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
    
    friend std::ostream &operator<<(std::ostream &os, const Date &d) {
      return os << d.year_ << '-' << d.month_ << '-' << d.day_;
    }
    };
    
    std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
    // s == "The date is 2012-12-9"
    
  • Added support for custom argument formatters (https://github.com/fmtlib/fmt/issues/235).

  • Added support for locale-specific integer formatting with the n specifier (https://github.com/fmtlib/fmt/issues/305):

    std::setlocale(LC_ALL, "en_US.utf8");
    fmt::print("cppformat: {:n}\n", 1234567); // prints 1,234,567
    
  • Sign is now preserved when formatting an integer with an incorrect printf format specifier (https://github.com/fmtlib/fmt/issues/265):

    fmt::printf("%lld", -42); // prints -42
    

Note that it would be an undefined behavior in std::printf.

  • Length modifiers such as ll are now optional in printf formatting functions and the correct type is determined automatically (https://github.com/fmtlib/fmt/issues/255):

    fmt::printf("%d", std::numeric_limits<long long>::max());
    

Note that it would be an undefined behavior in std::printf.

Thanks @dean0x7d.

2.1.1 - 2016-04-11

2.1.0 - 2016-03-21

  • Project layout and build system improvements (https://github.com/fmtlib/fmt/pull/267):

    • The code have been moved to the cppformat directory. Including format.h from the top-level directory is deprecated but works via a proxy header which will be removed in the next major version.
    • C++ Format CMake targets now have proper interface definitions.
    • Installed version of the library now supports the header-only configuration.
    • Targets doc, install, and test are now disabled if C++ Format is included as a CMake subproject. They can be enabled by setting FMT_DOC, FMT_INSTALL, and FMT_TEST in the parent project.

Thanks @niosHD.

2.0.1 - 2016-03-13

2.0.0 - 2015-12-01

General

Thanks @jamboree.

Thanks @dean0x7d.

Thanks @jamboree.

To print bool as a number use numeric format specifier such as d:

  fmt::print("{:d}", true); // prints "1"
  • fmt::printf and fmt::sprintf now support formatting of bool with the %s specifier giving textual output, \"true\" or \"false\" (https://github.com/fmtlib/fmt/pull/223):

    fmt::printf("%s", true); // prints "true"
    

Thanks @LarsGullik.

Thanks @LarsGullik.

References to null-terminated strings are now represented by a new class, BasicCStringRef.

Optimization

Distribution

Thanks @jackyf.

Thanks @ortho and Anatoliy Bulukin.

Documentation

Fixes

Thanks @Naios.

1.1.0 - 2015-03-06

You can now install C++ Format with make install command.

The android-ndk-example repository provides and example of using C++ Format with Android NDK:

1.0.0 - 2015-02-05

0.12.0 - 2014-10-25

  • [Breaking] Improved separation between formatting and buffer management. Writer is now a base class that cannot be instantiated directly. The new MemoryWriter class implements the default buffer management with small allocations done on stack. So fmt::Writer should be replaced with fmt::MemoryWriter in variable declarations.

Old code:

  fmt::Writer w;

New code:

  fmt::MemoryWriter w;

If you pass fmt::Writer by reference, you can continue to do so:

  void f(fmt::Writer &w);

This doesn\'t affect the formatting API.

| Old | New | | --- | --- | | | |

0.11.0 - 2014-08-21

  • Safe printf implementation with a POSIX extension for positional arguments:

    fmt::printf("Elapsed time: %.2f seconds", 1.23);
    fmt::printf("%1$s, %3$d %2$s", weekday, month, day);
    
  • Arguments of char type can now be formatted as integers (Issue https://github.com/fmtlib/fmt/issues/55):

    fmt::format("0x{0:02X}", 'a');
    
  • Deprecated parts of the API removed.

  • The library is now built and tested on MinGW with Appveyor in addition to existing test platforms Linux/GCC, OS X/Clang, Windows/MSVC.

0.10.0 - 2014-07-01

Improved API

  • All formatting methods are now implemented as variadic functions instead of using operator<< for feeding arbitrary arguments into a temporary formatter object. This works both with C++11 where variadic templates are used and with older standards where variadic functions are emulated by providing lightweight wrapper functions defined with the FMT_VARIADIC macro. You can use this macro for defining your own portable variadic functions:

    void report_error(const char *format, const fmt::ArgList &args) {
    fmt::print("Error: {}");
    fmt::print(format, args);
    }
    FMT_VARIADIC(void, report_error, const char *)
    
    report_error("file not found: {}", path);
    

Apart from a more natural syntax, this also improves performance as there is no need to construct temporary formatter objects and control arguments\' lifetimes. Because the wrapper functions are very lightweight, this doesn\'t cause code bloat even in pre-C++11 mode.

  • Simplified common case of formatting an std::string. Now it requires a single function call:

    std::string s = format("The answer is {}.", 42);
    

Previously it required 2 function calls:

  std::string s = str(Format("The answer is {}.") << 42);

Instead of unsafe c_str function, fmt::Writer should be used directly to bypass creation of std::string:

  fmt::Writer w;
  w.write("The answer is {}.", 42);
  w.c_str();  // returns a C string

This doesn\'t do dynamic memory allocation for small strings and is less error prone as the lifetime of the string is the same as for std::string::c_str which is well understood (hopefully).

  • Improved consistency in naming functions that are a part of the public API. Now all public functions are lowercase following the standard library conventions. Previously it was a combination of lowercase and CapitalizedWords. Issue https://github.com/fmtlib/fmt/issues/50.

  • Old functions are marked as deprecated and will be removed in the next release.

Other Changes

  • Experimental support for printf format specifications (work in progress):

    fmt::printf("The answer is %d.", 42);
    std::string s = fmt::sprintf("Look, a %s!", "string");
    
  • Support for hexadecimal floating point format specifiers a and A:

    print("{:a}", -42.0); // Prints -0x1.5p+5
    print("{:A}", -42.0); // Prints -0X1.5P+5
    
  • CMake option FMT_SHARED that specifies whether to build format as a shared library (off by default).

0.9.0 - 2014-05-13

  • More efficient implementation of variadic formatting functions.

  • Writer::Format now has a variadic overload:

    Writer out;
    out.Format("Look, I'm {}!", "variadic");
    
  • For efficiency and consistency with other overloads, variadic overload of the Format function now returns Writer instead of std::string. Use the str function to convert it to std::string:

    std::string s = str(Format("Look, I'm {}!", "variadic"));
    
  • Replaced formatter actions with output sinks: NoAction -> NullSink, Write -> FileSink, ColorWriter -> ANSITerminalSink. This improves naming consistency and shouldn\'t affect client code unless these classes are used directly which should be rarely needed.

  • Added ThrowSystemError function that formats a message and throws SystemError containing the formatted message and system-specific error description. For example, the following code

    FILE *f = fopen(filename, "r");
    if (!f)
    ThrowSystemError(errno, "Failed to open file '{}'") << filename;
    

will throw SystemError exception with description \"Failed to open file \'<filename>\': No such file or directory\" if file doesn\'t exist.

  • Support for AppVeyor continuous integration platform.

  • Format now throws SystemError in case of I/O errors.

  • Improve test infrastructure. Print functions are now tested by redirecting the output to a pipe.

0.8.0 - 2014-04-14

  • Initial release