llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.32k stars 11.69k forks source link

Cannot format a duration with unsigned (or user-defined) representation #96820

Closed dangelog closed 2 months ago

dangelog commented 3 months ago

Testcase: https://godbolt.org/z/EM7WxfEfT

#include <chrono>
#include <format>

int main()
{
    (void)
        std::format("{}", std::chrono::duration<unsigned>{});
}

Does not build:

In file included from /opt/compiler-explorer/clang-trunk-20240626/bin/../include/c++/v1/chrono:952:
/opt/compiler-explorer/clang-trunk-20240626/bin/../include/c++/v1/__chrono/formatter.h:594:63: error: no matching function for call to 'abs'
  594 |       __formatter::__format_chrono_using_chrono_specs(__sstr, chrono::abs(__value), __chrono_specs);
      |                                                               ^~~~~~~~~~~

chrono::abs is constrained for durations whose representation type is signed. This excludes unsigned types as well as any user-defined representation type.

Matching bug in libstdc++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115668

frederick-vs-ja commented 3 months ago

For user-defined representation types, see also microsoft/STL#1909. The requirement "a class emulating an arithmetic type" ([tab:time.clock]) is too imprecise to be honored by implementations.

dangelog commented 3 months ago

I'd agree. I'm going to open a library defect for that.

jwakely commented 3 months ago

This excludes unsigned types as well as any user-defined representation type.

Not if you specialize numeric_limits for your user-defined rep, which is probably a good idea for something trying to act like a numeric type (and means you don't need to specialize chrono::duration_values).

mordante commented 3 months ago

Actually it seems there are other issues with this formatter. [time.duration.general]/2

  Rep shall be an arithmetic type or ...

This allows Rep to be unsigned char, bool, char8_t, etc. These duration specializations then should be streamed to an ostream. unsigned char is on its way to be deprecated by P3154R1 and char8_t does not work. (There might be other issues too.)

For now I'll look at unsigned short, unsigned, unsigned long, and unsigned long long. I hope to find time to write an LWG-issue/paper to discuss whether arithmetic types is the proper set.

@dangelog can you post the LWG number here once you have one?

jwakely commented 3 months ago

This allows Rep to be unsigned char, bool, char8_t, etc. These duration specializations then should be streamed to an ostream. unsigned char is on its way to be deprecated by P3154R1 and char8_t does not work. (There might be other issues too.)

Yes, I have a draft LWG issue on that topic. The formatter for durations needs to be constrained to only accept formattable rep types.

dangelog commented 3 months ago

Hi,

@dangelog can you post the LWG number here once you have one?

Turns out that there were already a couple of defects in the area, jwakely kindly pointed me to them:

https://cplusplus.github.io/LWG/issue951 https://cplusplus.github.io/LWG/issue953

I still think that more clarifications are needed in the area...

jwakely commented 2 months ago

I've created LWG 4118 regarding formatting of durations with non-formattable rep types.