Skip to content

<chrono>: Using format with unsigned integer based chrono::time_point causes error C2672: 'std::chrono::abs': no matching overloaded function found #4144

Open
@StephanTLavavej

Description

@StephanTLavavej
C:\Temp>type meow.cpp
#include <chrono>
#include <format>
#include <iostream>
#include <string>
using namespace std;
using namespace std::chrono;

int main() {
    const sys_time<duration<unsigned int>> tp{};
    const string s = format("{:%Y-%m-%d %H:%M:%S}\n", tp);
    cout << s;
}
MSVC error:
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /std:c++latest /MTd /Od meow.cpp
meow.cpp
D:\GitHub\STL\out\x64\out\inc\chrono(1604): error C2672: 'std::chrono::abs': no matching overloaded function found
D:\GitHub\STL\out\x64\out\inc\__msvc_chrono.hpp(499): note: could be 'std::chrono::duration<_Rep,_Period> std::chrono::abs(const std::chrono::duration<_Rep,_Period>) noexcept(<expr>)'
D:\GitHub\STL\out\x64\out\inc\chrono(1604): note: 'std::chrono::duration<_Rep,_Period> std::chrono::abs(const std::chrono::duration<_Rep,_Period>) noexcept(<expr>)': could not deduce template argument for '__formal'
D:\GitHub\STL\out\x64\out\inc\__msvc_chrono.hpp(498): note: 'std::enable_if_t<false,int>' : Failed to specialize alias template
D:\GitHub\STL\out\x64\out\inc\chrono(1604): note: the template instantiation context (the oldest one first) is
meow.cpp(10): note: see reference to function template instantiation 'std::basic_format_string<char,const std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>> &>::basic_format_string<char[22]>(const _Ty (&))' being compiled
        with
        [
            _Ty=char [22]
        ]
D:\GitHub\STL\out\x64\out\inc\format(3802): note: see reference to class template instantiation 'std::__p2286::_Format_checker<_CharT,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>>' being compiled
        with
        [
            _CharT=char
        ]
D:\GitHub\STL\out\x64\out\inc\format(3579): note: while compiling class template member function 'std::__p2286::_Format_checker<_CharT,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>>::_Format_checker(std::basic_string_view<char,std::char_traits<char>>) noexcept'
        with
        [
            _CharT=char
        ]
D:\GitHub\STL\out\x64\out\inc\format(3580): note: see reference to function template instantiation 'std::_String_view_iterator<_Traits> std::__p2286::_Compile_time_parse_format_specs<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>,std::basic_format_parse_context<char>>(_ParseContext &)' being compiled
        with
        [
            _Traits=std::char_traits<char>,
            _ParseContext=std::basic_format_parse_context<char>
        ]
D:\GitHub\STL\out\x64\out\inc\format(3559): note: see reference to alias template instantiation 'std::_Format_arg_traits<_Context>::_Storage_type<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>>' being compiled
        with
        [
            _Context=std::format_context
        ]
D:\GitHub\STL\out\x64\out\inc\format(847): note: see reference to variable template 'bool _Formattable_with<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1> > >,std::basic_format_context<std::back_insert_iterator<std::_Fmt_buffer<char> >,char>,std::formatter<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1> > >,char> >' being compiled
D:\GitHub\STL\out\x64\out\inc\format(662): note: see reference to function template instantiation '_OutputIt std::formatter<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>,_CharT>::format<_Context>(const std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>> &,_FormatContext &) const' being compiled
        with
        [
            _OutputIt=std::back_insert_iterator<std::_Fmt_buffer<char>>,
            _CharT=char,
            _Context=std::format_context,
            _FormatContext=std::format_context
        ]
D:\GitHub\STL\out\x64\out\inc\chrono(5879): note: see reference to function template instantiation 'tm std::chrono::_Fill_tm<std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>>(const _Ty &)' being compiled
        with
        [
            _Ty=std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<unsigned int,std::ratio<1,1>>>
        ]
D:\GitHub\STL\out\x64\out\inc\chrono(4994): note: see reference to class template instantiation 'std::chrono::hh_mm_ss<std::chrono::duration<unsigned int,std::ratio<1,1>>>' being compiled
D:\GitHub\STL\out\x64\out\inc\chrono(1602): note: while compiling class template member function 'std::chrono::hh_mm_ss<std::chrono::duration<unsigned int,std::ratio<1,1>>>::hh_mm_ss(_Duration)'
        with
        [
            _Duration=std::chrono::duration<unsigned int,std::ratio<1,1>>
        ]
D:\GitHub\STL\out\x64\out\inc\chrono(5063): note: see the first reference to 'std::chrono::hh_mm_ss<std::chrono::duration<unsigned int,std::ratio<1,1>>>::hh_mm_ss' in 'std::chrono::_Fill_tm'
[...]
Clang error:
D:\GitHub\STL\out\x64>clang-cl /EHsc /nologo /W4 /std:c++latest /MTd /Od meow.cpp
In file included from meow.cpp:1:
D:\GitHub\STL\out\x64\out\inc\chrono(1604,70): error: no matching function for call to 'abs'
              _Hours{_Duration_cast_underflow_to_zero<_CHRONO hours>(_CHRONO abs(_Dur))},
                                                                     ^~~~~~~~~~~
D:\GitHub\STL\out\x64\out\inc\yvals_core.h(1947,20): note: expanded from macro '_CHRONO'
#define _CHRONO    ::std::chrono::
                   ^
D:\GitHub\STL\out\x64\out\inc\chrono(5063,28): note: in instantiation of member function
      'std::chrono::hh_mm_ss<std::chrono::duration<unsigned int>>::hh_mm_ss' requested here
            const hh_mm_ss _Time{_Val - _Dp};
                           ^
D:\GitHub\STL\out\x64\out\inc\chrono(5879,47): note: in instantiation of function template specialization
      'std::chrono::_Fill_tm<std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<unsigned int>>>'
      requested here
        return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Val));
                                              ^
D:\GitHub\STL\out\x64\out\inc\__msvc_chrono.hpp(499,50): note: candidate template ignored: requirement
      'numeric_limits<unsigned int>::is_signed' was not satisfied [with _Rep = unsigned int, _Period = std::ratio<1>]
    _NODISCARD constexpr duration<_Rep, _Period> abs(const duration<_Rep, _Period> _Dur) noexcept(
                                                 ^
[...]

WG21-N4964 [time.duration.alg]/1 says for chrono::abs(duration<Rep, Period>):

Constraints: numeric_limits<Rep>::is_signed is true.

[time.hms.members]/3 says that chrono::hh_mm_ss(Duration d) uses abs(d).

We use chrono::hh_mm_ss to implement chrono formatting:

const hh_mm_ss _Time{_Val - _Dp};

But I see nothing in [time.format] that allows us to reject unsigned durations in chrono formatting.

Originally reported as DevCom-10501153 / VSO-1910245 / AB#1910245 .

As mentioned in the original bug report, GCC/libstdc++ and Clang/libc++ accept this code: https://godbolt.org/z/n9EGxzY46

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingchronoC++20 chronoformatC++20/23 format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions