This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.

2383. Overflow cannot be ill-formed for chrono::duration integer literals

Section: 30.5.9 [time.duration.literals] Status: Open Submitter: Jonathan Wakely Opened: 2014-05-16 Last modified: 2026-06-16

Priority: 3

View all issues with Open status.

Discussion:

30.5.9 [time.duration.literals] p3 says:

If any of these suffixes are applied to an integer literal and the resulting chrono::duration value cannot be represented in the result type because of overflow, the program is ill-formed.

Ill-formed requires a diagnostic at compile-time, but there is no way to detect the overflow from unsigned long long to the signed duration<>::rep type.

Overflow could be detected if the duration integer literals were literal operator templates, otherwise overflow can either be undefined or a run-time error, not ill-formed.

[Urbana 2014-11-07: Move to Open]

[2026-06-16; Jonathan adds wording.]

The library has no way to distinguish the case where a suffix is "applied to an integer literal", as opposed to using function call notation like operator""s(123). There is never overflow, because converting unsigned long long to a rep such as signed long long is always well-formed, just not value-preserving. Unless it is used as a constant subexpression, a user-defined-literal such as 123s is not constant evaluated, so in general checking the value at compile-time is unimplementable.

If we made these operators consteval then using them as the suffix of a user-defined-literal would always be a constant expression. It would make it ill-formed to call operator""s(some_variable) but I consider that perfectly acceptable. Such uses are absurd, and the existing wording is all specified in terms of suffixes anyway, not in terms of function calls to those operators. P3931R0 proposes making these (and other literal operators) consteval, which would resolve this issue by making it implementable.

Alternatively, we could permit the integral literal operators to be implemented as literal operator templates, i.e. template<char... Digits>, as this makes it possible to check for overflow. This is what libstdc++ has done since the duration literals were first implemented.

Alternatively, we could just remove the rule saying that overflow is detected. Neither libc++ nor MSVC implements the overflow check, so if it was a problem that affects many users we'd have heard about it.

Proposed resolution:

This wording is relative to N5046.

Three options are presented, choose only one.
Option A
  1. Modify 30.5.9 [time.duration.literals] as indicated:

    -1- This subclause describes literal suffixes for constructing duration literals. The suffixes h, min, s, ms, us, ns denote duration values of the corresponding types hours, minutes, seconds, milliseconds, microseconds, and nanoseconds respectively if they are applied to integer-literals.

    -2- If any of these suffixes are is applied to a floating-point-literal the result is a chrono::duration literal with an unspecified floating-point representation.

    -3- If any of these suffixes are is applied to an integer-literal and the parameter cannot be represented in the rep type of the return type, the resulting chrono::duration value cannot be represented in the result type because of overflow, the program is ill-formed.

    -4- [Example 1: The following code shows some duration literals.

    using namespace std::chrono_literals;
    auto constexpr aday=24h;
    auto constexpr lesson=45min;
    auto constexpr halfanhour=0.5h;
    
    end example]

    constexpr consteval chrono::hours                                 operator""h(unsigned long long hours);
    constexpr consteval chrono::duration<unspecified, ratio<3600, 1>> operator""h(long double hours);
    

    -5- Returns: A duration literal value representing hours hours.

    constexpr consteval chrono::minutes                             operator""min(unsigned long long minutes);
    constexpr consteval chrono::duration<unspecified, ratio<60, 1>> operator""min(long double minutes);
    

    -6- Returns: A duration literal value representing minutes minutes.

    constexpr consteval chrono::seconds               operator""s(unsigned long long seconds);
    constexpr consteval chrono::duration<unspecified> operator""s(long double seconds);
    

    -7- Returns: A duration literal value representing seconds seconds.

    -8- [Note 1: The same suffix s is used for basic_string but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals. — end note]

    constexpr consteval chrono::milliseconds                operator""ms(unsigned long long msec);
    constexpr consteval chrono::duration<unspecified, milli> operator""ms(long double msec);
    

    -9- Returns: A duration literal value representing msec milliseconds.

    constexpr consteval chrono::microseconds                operator""us(unsigned long long usec);
    constexpr consteval chrono::duration<unspecified, micro> operator""us(long double usec);
    

    -10- Returns: A duration literal value representing usec microseconds.

    constexpr consteval chrono::nanoseconds                operator""ns(unsigned long long nsec);
    constexpr consteval chrono::duration<unspecified, nano> operator""ns(long double nsec);
    

    -11- Returns: A duration literal value representing nsec nanoseconds.

  2. Add [diff.cpp26.duration] to Annex C:

    C.1.? Clause 30 [time]: Time library

    Affected subclause: 30.5.9 [time.duration.literals]

    Change: Literal operators for duration literals are immediate functions.

    Rationale: Allow checking for overflow.

    Effect on original feature: Valid C++ 2026 code that used function call syntax and non-constant arguments to create duration literals is ill-formed in this document.

    [Example ?:

    int n = 60;
    auto t = std::chrono::literals::operator""s(n); // ill-formed; previously well-formed
    
    end example]

Option B
  1. Modify 30.5.9 [time.duration.literals] as indicated:

    -1- This subclause describes literal suffixes for constructing duration literals. The suffixes h, min, s, ms, us, ns denote duration values of the corresponding types hours, minutes, seconds, milliseconds, microseconds, and nanoseconds respectively if they are applied to integer-literals.

    -2- If any of these suffixes are is applied to a floating-point-literal the result is a chrono::duration literal with an unspecified floating-point representation.

    -3- If any of these suffixes are is applied to an integer-literal and the parameter cannot be represented in the rep type of the return type, the resulting chrono::duration value cannot be represented in the result type because of overflow, the program is ill-formed.

    -?- It is unspecified whether the literal operators below are usable only as the suffix of a user-defined-literal (5.13.9 [lex.ext]), or whether they can also be called using function call notation. If they can be called using function call notation, using unsigned long long parameters that cannot be represented in the rep type of the return type is ill-formed, no diagnostic required.

    Option B should also do the "duration literal value" drive-by fix, and probably update Annex C as well.
Option C
  1. Modify 30.5.9 [time.duration.literals] as indicated:

    -1- This subclause describes literal suffixes for constructing duration literals. The suffixes h, min, s, ms, us, ns denote duration values of the corresponding types hours, minutes, seconds, milliseconds, microseconds, and nanoseconds respectively if they are applied to integer-literals.

    -2- If any of these suffixes are is applied to a floating-point-literal the result is a chrono::duration literal with an unspecified floating-point representation.

    -3- If any of these suffixes are applied to an integer-literal and the resulting chrono::duration value cannot be represented in the result type because of overflow, the program is ill-formed.