This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
Section: 29.5.2 [time.duration.cons], 29.5.6 [time.duration.nonmember] Status: C++20 Submitter: Barry Revzin Opened: 2018-01-22 Last modified: 2021-02-25
Priority: 3
View all other issues in [time.duration.cons].
View all issues with C++20 status.
Discussion:
The converting constructor in std::chrono::duration is currently specified as (29.5.2 [time.duration.cons] p1):
template<class Rep2> constexpr explicit duration(const Rep2& r);Remarks: This constructor shall not participate in overload resolution unless Rep2 is implicitly convertible to rep and […]
But the parameter is of type Rep2 const, so we should check that Rep2 const is implicitly convertible to rep, not just Rep2. This means that for a type like:
struct X { operator int64_t() /* not const */; };
std::is_constructible_v<std::chrono::seconds, X> is true, but actual construction will fail to compile.
Further analysis of sub-clause 29.5 [time.duration] revealed similar specification problems in some other functions.[2018-06 Rapperswil Thursday issues processing]
P3; Status to Open
[2018-11 San Diego Thursday night issue processing]
Jonathan to provide updated wording; the underlying text has changed.
[2018-12-05 Jonathan provides new wording]
In San Diego Geoff noticed that the current WP does not use CR. Jonathan provides new wording consistent with the editorial changes that removed CR.
Previous resolution [SUPERSEDED]:Previous resolution [SUPERSEDED]:This wording is relative to N4713.
Modify 29.5.2 [time.duration.cons] as indicated:
template<class Rep2> constexpr explicit duration(const Rep2& r);-1- Remarks: This constructor shall not participate in overload resolution unless is_convertible_v<const Rep2&, rep> is true
Rep2 is implicitly convertible to repand[…] -2- Effects: Constructs an object of type duration. -3- Postconditions: count() == static_cast<rep>(r).
(1.1) — treat_as_floating_point_v<rep> is true or
(1.2) — treat_as_floating_point_v<Rep2> is false.
Modify 29.5.6 [time.duration.nonmember] as indicated:
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s);-4- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, CR(Rep1, Rep2)> is true
[…]Rep2 is implicitly convertible to CR(Rep1, Rep2).template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d);-6- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep1&, CR(Rep1, Rep2)> is true
[…]Rep1 is implicitly convertible to CR(Rep1, Rep2).template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s);[…]-8- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, CR(Rep1, Rep2)> is true
Rep2 is implicitly convertible to CR(Rep1, Rep2)and Rep2 is not a specialization of duration.template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s);-11- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, CR(Rep1, Rep2)> is true
[…]Rep2 is implicitly convertible to CR(Rep1, Rep2)and Rep2 is not a specialization of duration.
This wording is relative to N4791.
Modify 29.5.2 [time.duration.cons] as indicated:
template<class Rep2> constexpr explicit duration(const Rep2& r);-1- Remarks: This constructor shall not participate in overload resolution unless is_convertible_v<const Rep2&, rep> is true
Rep2 is implicitly convertible to repand[…] -2- Effects: Constructs an object of type duration. -3- Postconditions: count() == static_cast<rep>(r).
(1.1) — treat_as_floating_point_v<rep> is true or
(1.2) — treat_as_floating_point_v<Rep2> is false.
Modify 29.5.6 [time.duration.nonmember] as indicated:
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s);-4- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true
[…]Rep2 is implicitly convertible to common_type_t<Rep1, Rep2>.template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d);-6- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep1&, common_type_t<Rep1, Rep2>> is true
[…]Rep1 is implicitly convertible to common_type_t<Rep1, Rep2>.template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s);[…]-8- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true
Rep2 is implicitly convertible to common_type_t<Rep1, Rep2>and Rep2 is not a specialization of duration.template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s);-11- Remarks: This operator shall not participate in overload resolution unless is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true
[…]Rep2 is implicitly convertible to common_type_t<Rep1, Rep2>and Rep2 is not a specialization of duration.
[2020-02-13, Prague]
Rebase to most recent working draft
[2020-02 Status to Immediate on Thursday night in Prague.]
Proposed resolution:
This wording is relative to N4849.
Modify 29.5.2 [time.duration.cons] as indicated:
template<class Rep2> constexpr explicit duration(const Rep2& r);-1- Constraints: is_convertible_v<const Rep2&, rep> is true and
[…] -2- Postconditions: count() == static_cast<rep>(r).
(1.1) — treat_as_floating_point_v<rep> is true or
(1.2) — treat_as_floating_point_v<Rep2> is false.
Modify 29.5.6 [time.duration.nonmember] as indicated:
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s);-4- Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true.
[…]template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d);-6- Constraints: is_convertible_v<const Rep1&, common_type_t<Rep1, Rep2>> is true.
[…]template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s);[…]-8- Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true and Rep2 is not a specialization of duration.
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s);-12- Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true and Rep2 is not a specialization of duration.
[…]