Section: 30.5.2 [time.duration.cons] Status: New Submitter: Richard Smith Opened: 2018-03-22 Last modified: 2020-09-12
Priority: 3
View all other issues in [time.duration.cons].
View all issues with New status.
Discussion:
30.5.2 [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>
istrue
or bothratio_divide<Period2, period>::den
is 1 andtreat_as_floating_point_v<Rep2>
isfalse
.
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.
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 convertPeriod2
toPeriod
. 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?
[2018-06-18 after reflector discussion]
Priority set to 3
[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
.
Proposed resolution:
This wording is relative to N4861.
Modify 30.5.2 [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
[Note: This requirement prevents implicit truncation errors
when converting between integral-based 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
.
duration
types.
Such a construction could easily lead to confusion about the value of the
duration
.
— end note]