Repository: fmtlib/fmt
File: include/fmt/chrono.h (C/C++)

Code before:
// Prevents expansion of a preceding token as a function-style macro.
// Usage: f FMT_NOMACRO()
#define FMT_NOMACRO

namespace detail {
template <typename T = void> struct null {};
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
inline null<> localtime_s(...) { return null<>(); }
inline null<> gmtime_r(...) { return null<>(); }
inline null<> gmtime_s(...) { return null<>(); }

template <typename Char>
inline auto do_write(const std::tm& time, const std::locale& loc, char format,
                     char modifier)
    -> decltype(std::basic_ostringstream<Char>().str()) {
  auto&& os = std::basic_ostringstream<Char>();
  os.imbue(loc);
  using iterator = std::ostreambuf_iterator<Char>;
  const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc);
  auto end = facet.put(os, os, Char(' '), &time, format, modifier);
  if (end.failed()) FMT_THROW(format_error("failed to format time"));
  return std::move(os).str();
}

template <typename Char, typename OutputIt>
auto write(Char, OutputIt out, const std::tm& time, const std::locale& loc,
           char format, char modifier = 0) -> OutputIt {
  auto str = do_write<Char>(time, loc, format, modifier);
  return std::copy(str.begin(), str.end(), out);
}

template <typename OutputIt>
auto write(char, OutputIt out, const std::tm& time, const std::locale& loc,
           char format, char modifier = 0) -> OutputIt {
  auto str = do_write<char>(time, loc, format, modifier);
  if (detail::is_utf8() && loc != std::locale::classic()) {
    // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
    // gcc-4.
#if FMT_MSC_VER != 0 || \
    (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
    // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
    // and newer.
    using code_unit = wchar_t;
#else
    using code_unit = char32_t;
#endif

    using codecvt = std::codecvt<code_unit, char, std::mbstate_t>;
#if FMT_CLANG_VERSION
#  pragma clang diagnostic push
#  pragma clang diagnostic ignored "-Wdeprecated"

Review comment (performance):
Let's not pass an unused parameter here. I think you can merge the two `write` overloads and add a check like:

```c++
  if (sizeof(Char) == 1 && detail::is_utf8() && loc != std::locale::classic()) {
```

This will be optimized away for the `wchar_t` case.

Code after:
// Prevents expansion of a preceding token as a function-style macro.
// Usage: f FMT_NOMACRO()
#define FMT_NOMACRO

namespace detail {
template <typename T = void> struct null {};
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
inline null<> localtime_s(...) { return null<>(); }
inline null<> gmtime_r(...) { return null<>(); }
inline null<> gmtime_s(...) { return null<>(); }

template <typename Char>
inline auto do_write(const std::tm& time, const std::locale& loc, char format,
                     char modifier) -> std::basic_string<Char> {
  auto&& os = std::basic_ostringstream<Char>();
  os.imbue(loc);
  using iterator = std::ostreambuf_iterator<Char>;
  const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc);
  auto end = facet.put(os, os, Char(' '), &time, format, modifier);
  if (end.failed()) FMT_THROW(format_error("failed to format time"));
  return std::move(os).str();
}

template <typename Char, typename OutputIt,
          FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
auto write(OutputIt out, const std::tm& time, const std::locale& loc,
           char format, char modifier = 0) -> OutputIt {
  auto str = do_write<Char>(time, loc, format, modifier);
  return std::copy(str.begin(), str.end(), out);
}

template <typename Char, typename OutputIt,
          FMT_ENABLE_IF(std::is_same<Char, char>::value)>
auto write(OutputIt out, const std::tm& time, const std::locale& loc,
           char format, char modifier = 0) -> OutputIt {
  auto str = do_write<char>(time, loc, format, modifier);
  if (detail::is_utf8() && loc != std::locale::classic()) {
    // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
    // gcc-4.
#if FMT_MSC_VER != 0 || \
    (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
    // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
    // and newer.
    using code_unit = wchar_t;
#else
    using code_unit = char32_t;
#endif

    using codecvt = std::codecvt<code_unit, char, std::mbstate_t>;
#if FMT_CLANG_VERSION
#  pragma clang diagnostic push