Title
Conversion specification problem in chrono::duration constructor
Status
c++20
Section
[time.duration.cons][time.duration.nonmember]
Submitter
Barry Revzin

Created on 2018-01-11.00:00:00 last changed 45 months ago

Messages

Date: 2020-02-14.09:37:04

Proposed resolution:

This wording is relative to N4849.

  1. Modify [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

    1. (1.1) — treat_as_floating_point_v<rep> is true or

    2. (1.2) — treat_as_floating_point_v<Rep2> is false.

    […]

    -2- Postconditions: count() == static_cast<rep>(r).

  2. Modify [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.

    […]

Date: 2020-02-14.09:37:04

[ 2020-02 Status to Immediate on Thursday night in Prague. ]

Date: 2020-02-15.00:00:00

[ 2020-02-13, Prague ]

Rebase to most recent working draft

Date: 2018-12-05.00:00:00

[ 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]:

This wording is relative to N4713.

  1. Modify [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 trueRep2 is implicitly convertible to rep and

    1. (1.1) — treat_as_floating_point_v<rep> is true or

    2. (1.2) — treat_as_floating_point_v<Rep2> is false.

    […]

    -2- Effects: Constructs an object of type duration.

    -3- Postconditions: count() == static_cast<rep>(r).

  2. Modify [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 trueRep2 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 trueRep1 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 trueRep2 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 trueRep2 is implicitly convertible to CR(Rep1, Rep2) and Rep2 is not a specialization of duration.

    […]

Previous resolution [SUPERSEDED]:

This wording is relative to N4791.

  1. Modify [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 trueRep2 is implicitly convertible to rep and

    1. (1.1) — treat_as_floating_point_v<rep> is true or

    2. (1.2) — treat_as_floating_point_v<Rep2> is false.

    […]

    -2- Effects: Constructs an object of type duration.

    -3- Postconditions: count() == static_cast<rep>(r).

  2. Modify [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 trueRep2 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 trueRep1 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 trueRep2 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 trueRep2 is implicitly convertible to common_type_t<Rep1, Rep2> and Rep2 is not a specialization of duration.

    […]

Date: 2018-11-12.05:21:03

[ 2018-11 San Diego Thursday night issue processing ]

Jonathan to provide updated wording; the underlying text has changed.

Date: 2018-06-12.04:35:59

[ 2018-06 Rapperswil Thursday issues processing ]

P3; Status to Open

Date: 2018-01-25.19:13:09

The converting constructor in std::chrono::duration is currently specified as ([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 [time.duration] revealed similar specification problems in some other functions.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-02-24 16:02:59adminsetstatus: immediate -> wp
2020-02-14 09:37:04adminsetmessages: + msg11104
2020-02-14 09:37:04adminsetstatus: open -> immediate
2020-02-13 18:57:08adminsetmessages: + msg11080
2018-12-04 22:42:34adminsetmessages: + msg10247
2018-11-12 05:21:03adminsetmessages: + msg10215
2018-06-12 04:35:59adminsetmessages: + msg9910
2018-06-12 04:35:59adminsetstatus: new -> open
2018-01-23 19:57:43adminsetmessages: + msg9622
2018-01-23 19:57:43adminsetmessages: + msg9621
2018-01-23 19:57:43adminrestored
2018-01-14 13:56:30adminretired
2018-01-14 13:56:30adminsetmessages: - msg9604, msg9605
2018-01-13 19:29:23adminsetmessages: + msg9605
2018-01-11 00:00:00admincreate