Skip to content

Printing std::chrono::time_point requires std::to_chars<long double> #125353

@georgthegreat

Description

@georgthegreat

MWE (using gtest here) is as follows:

#include <chrono>
#include <format>
#include <sstream>


TEST(StdFormatShould, FormatTimestamp) {
    using Ts = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
    Ts ts{0};
    std::stringstream ss;
    ss << ts;
}

Attempting to compile this on macOS with the latest SDK results in

In file included from test_format.cpp:1:
In file included from /usr/include/c++/v1/chrono:837:
In file included from /usr/include/c++/v1/__chrono/formatter.h:23:
In file included from /usr/include/c++/v1/__chrono/ostream.h:30:
In file included from /usr/include/c++/v1/__format/format_functions.h:29:
/usr/include/c++/v1/__format/formatter_floating_point.h:73:30: error: 'to_chars' is unavailable: introduced in macOS 13.3
   73 |   to_chars_result __r = std::to_chars(__first, __last, __value, __fmt, __precision);
      |                              ^
/usr/include/c++/v1/__format/formatter_floating_point.h:392:34: note: in instantiation of function template specialization 'std::__formatter::__to_buffer<float>' requested here
  392 |   __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision);
      |                                  ^
/usr/include/c++/v1/__format/formatter_floating_point.h:459:27: note: in instantiation of function template specialization 'std::__formatter::__format_buffer_general_lower_case<float, float>' requested here
  459 |       return __formatter::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first);
      |                           ^
/usr/include/c++/v1/__format/formatter_floating_point.h:657:42: note: in instantiation of function template specialization 'std::__formatter::__format_buffer<float, float>' requested here
  657 |   __float_result __result = __formatter::__format_buffer(
      |                                          ^
/usr/include/c++/v1/__format/formatter_floating_point.h:763:25: note: in instantiation of function template specialization 'std::__formatter::__format_floating_point<float, char, std::format_context>' requested here
  763 |     return __formatter::__format_floating_point(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
      |                         ^
/usr/include/c++/v1/__format/format_functions.h:287:42: note: in instantiation of function template specialization 'std::__formatter_floating_point<char>::format<float, std::format_context>' requested here
  287 |             __ctx.advance_to(__formatter.format(__arg, __ctx));
      |                                          ^
/usr/include/c++/v1/__format/format_functions.h:427:15: note: (skipping 9 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
  427 |   return std::__vformat_to(std::move(__out_it), __fmt, __args);
      |               ^
/usr/include/c++/v1/__format/format_arg_store.h:249:19: note: in instantiation of function template specialization 'std::__format::__create_packed_storage<std::format_context, const std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000>>>>' requested here
  249 |         __format::__create_packed_storage(__storage.__types_, __storage.__values_, __args...);
      |                   ^
/usr/include/c++/v1/__format/format_functions.h:70:10: note: in instantiation of member function 'std::__format_arg_store<std::format_context, const std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000>>>>::__format_arg_store' requested here
   70 |   return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
      |          ^
/usr/include/c++/v1/__config:897:17: note: expanded from macro '_VSTD'
  897 | #  define _VSTD std
      |                 ^
/usr/include/c++/v1/__format/format_functions.h:610:59: note: in instantiation of function template specialization 'std::make_format_args<std::format_context, const std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000>>>>' requested here
  610 |   return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...));
      |                                                           ^
/usr/include/c++/v1/__chrono/ostream.h:48:23: note: in instantiation of function template specialization 'std::format<const std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000>>> &>' requested here
   48 |   return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
      |                       ^
test_format.cpp:10:5: note: in instantiation of function template specialization 'std::chrono::operator<<<char, std::char_traits<char>, std::chrono::duration<long long, std::ratio<1, 1000>>>' requested here
   10 |         ss << ts;
      |            ^

This is probably related to the format used here which uses %F:

f, F: Produces the output as if by calling
std::to_chars(first, last, value, std::chars_format::fixed, precision) where precision is the specified precision, or 6 if precision is not specified.

despite being explicitly annotated with !treat_as_floating_point_v<typename _Duration::rep>

macOS 13.3 was releases just 2 years ago and we can no raise -mmacos-system-min to this value just to fix the test.

@ldionne, could you, please, take a look?
There is probably nothing that can be done to fix current SDKs already available (except weird patches applied to the client code), but new versions might have this fixed.

Metadata

Metadata

Assignees

Labels

libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.platform:macos

Type

No type

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions