Title
What is §[time.duration.cons]p4's "no overflow is induced in the conversion" intended to mean?
Status
new
Section
[time.duration.cons]
Submitter
Richard Smith

Created on 2018-03-22.00:00:00 last changed 1 month ago

Messages

Date: 2020-09-12.11:59:20

Proposed resolution:

This wording is relative to N4861.

  1. Modify [time.duration.cons] as indicated:

    template<class Rep2, class Period2>
      constexpr duration(const duration<Rep2, Period2>& d);
    

    -3- Constraints: is_convertible_v<const Rep2&, rep> is true. ratio_divide<typename Period2::type, period> is a valid ratio specialization. Either:

    • treat_as_floating_point_v<rep> is true; or
    • ratio_divide<Period2, period>::den is 1 and treat_as_floating_point_v<Rep2> is false.

    No overflow is induced in the conversion and treat_as_floating_point_v<rep> is true or both ratio_divide<Period2, period>::den is 1 and treat_as_floating_point_v<Rep2> is false. [Note: This requirement prevents implicit truncation errors when converting between integral-based duration types. Such a construction could easily lead to confusion about the value of the duration. — end note]

Date: 2020-09-12.00:00:00

[ 2020-09-12 Jonathan adds a proposed resolution ]

Since the result of the ratio_divide has to be a ratio, if it's not representable then the result simply isn't a valid type. Implementations are not required to make ratio_divide SFINAE-friendly to implement this constraint. They can perform the equivalent calculations to check if they would overflow, without actually using ratio_divide.

Date: 2018-06-18.00:00:00

[ 2018-06-18 after reflector discussion ]

Priority set to 3

Date: 2018-03-22.00:00:00

[time.duration.cons] p4 says:

template<class Rep2, class Period2>
  constexpr duration(const duration<Rep2, Period2>& d);

Remarks: This constructor shall not participate in overload resolution unless no overflow is induced in the conversion and treat_as_floating_point_v<rep> is true or both ratio_divide<Period2, period>::den is 1 and treat_as_floating_point_v<Rep2> is false.

with this example:

duration<int, milli> ms(3);
duration<int, micro> us = ms;  // OK
duration<int, milli> ms2 = us; // error

It's unclear to me what "no overflow is induced in the conversion" means in the above. What happens here:

duration<int, milli> ms(INT_MAX);
duration<int, micro> us = ms;  // ???

An overflow is clearly induced in the conversion here: internally, we'll multiply INT_MAX by 1000. But that cannot be determined statically (in general), and so can't affect the result of overload resolution.

So what's actually supposed to happen? Are we actually just supposed to check that Rep2 is no larger than Rep? (If so, what happens on overflow? Undefined behavior?)

It has been pointed out by Howard Hinnant:

This refers to the compile-time conversion factor to convert Period2 to Period. If that conversion factor is not representable as a (reduced) ratio<N, D>, then the constructor is SFINAE'd out. This might happen (for example) converting years to picoseconds.

I would not have guessed that from the wording. Maybe replacing "no overflow is induced in the conversion" with "the result of ratio_divide<Period2, Period> is representable as a ratio" or similar would help?

History
Date User Action Args
2020-09-12 11:59:20adminsetmessages: + msg11479
2020-09-12 11:59:20adminsetmessages: + msg11478
2018-06-19 05:49:11adminsetmessages: + msg9938
2018-03-22 00:00:00admincreate