1177. Improve "diagnostic required" wording

Section: 23.17.5 [time.duration] Status: C++11 Submitter: Howard Hinnant Opened: 2009-07-18 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [time.duration].

View all issues with C++11 status.

Discussion:

"diagnostic required" has been used (by me) for code words meaning "use enable_if to constrain templated functions. This needs to be improved by referring to the function signature as not participating in the overload set, and moving this wording to a Remarks paragraph.

[ 2009-10 Santa Cruz: ]

Moved to Ready.

[ 2009-11-19 Pete opens: ]

Oh, and speaking of 1177, most of the changes result in rather convoluted prose. Instead of saying

A shall be B, else C

it should be

C if A is not B

That is:

Rep2 shall be implicitly convertible to CR(Rep1, Rep2), else this signature shall not participate in overload resolution.

should be

This signature shall not participate in overload resolution if Rep2 is not implicitly convertible to CR(Rep1, Rep2).

That is clearer, and eliminates the false requirement that Rep2 "shall be" convertible.

[ 2009-11-19 Howard adds: ]

I've updated the wording to match Pete's suggestion and included bullet 16 from 1195.

[ 2009-11-19 Jens adds: ]

Further wording suggestion using "unless":

This signature shall not participate in overload resolution unless Rep2 is implicitly convertible to CR(Rep1, Rep2).

[ 2009-11-20 Howard adds: ]

I've updated the wording to match Jens' suggestion.

[ 2009-11-22 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]

Proposed resolution:

[ This proposed resolution addresses 947 and 974. ]

  1. Change 23.17.5.1 [time.duration.cons] (and reorder the Remarks paragraphs per 20.4.1.4 [structure.specifications]):

    template <class Rep2> 
      explicit duration(const Rep2& r);
    

    Requires: Remarks: This constructor shall not participate in overload resolution unless Rep2 shall be is implicitly convertible to rep and

    • treat_as_floating_point<rep>::value shall be is true, or
    • treat_as_floating_point<Rep2>::value shall be is false.

    Diagnostic required [Example:

    duration<int, milli> d(3); // OK 
    duration<int, milli> d(3.5); // error 
    

    end example]

    Effects: Constructs an object of type duration.

    Postcondition: count() == static_cast<rep>(r).

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

    Requires: Remarks: This constructor shall not participate in overload resolution unless treat_as_floating_point<rep>::value shall be is true or ratio_divide<Period2, period>::type::den shall be is 1. Diagnostic required. [Note: This requirement prevents implicit truncation error when converting between integral-based duration types. Such a construction could easily lead to confusion about the value of the duration. — end note] [Example:

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

    end example]

    Effects: Constructs an object of type duration, constructing rep_ from duration_cast<duration>(d).count().

  2. Change the following paragraphs in 23.17.5.5 [time.duration.nonmember]:

    template <class Rep1, class Period, class Rep2> 
      duration<typename common_type<Rep1, Rep2>::type, Period> 
      operator*(const duration<Rep1, Period>& d, const Rep2& s);
    

    Requires Remarks: This operator shall not participate in overload resolution unless Rep2 shall be is implicitly convertible to CR(Rep1, Rep2). Diagnostic required.

    template <class Rep1, class Period, class Rep2> 
      duration<typename common_type<Rep1, Rep2>::type, Period> 
      operator*(const Rep1& s, const duration<Rep2, Period>& d);
    

    Requires Remarks: This operator shall not participate in overload resolution unless Rep1 shall be is implicitly convertible to CR(Rep1, Rep2). Diagnostic required.

    template <class Rep1, class Period, class Rep2> 
      duration<typename common_type<Rep1, Rep2>::type, Period> 
      operator/(const duration<Rep1, Period>& d, const Rep2& s);
    

    Requires Remarks: This operator shall not participate in overload resolution unless Rep2 shall be is implicitly convertible to CR(Rep1, Rep2) and Rep2 shall not be is not an instantiation of duration. Diagnostic required.

    template <class Rep1, class Period, class Rep2> 
      duration<typename common_type<Rep1, Rep2>::type, Period> 
      operator%(const duration<Rep1, Period>& d, const Rep2& s);
    

    Requires Remarks: This operator shall not participate in overload resolution unless Rep2 shall be is implicitly convertible to CR(Rep1, Rep2) and Rep2 shall not be is not an instantiation of duration. Diagnostic required.

  3. Change the following paragraphs in 23.17.5.7 [time.duration.cast]:

    template <class ToDuration, class Rep, class Period> 
      ToDuration duration_cast(const duration<Rep, Period>& d);
    

    Requires Remarks: This function shall not participate in overload resolution unless ToDuration shall be is an instantiation of duration. Diagnostic required.

  4. Change 23.17.6.1 [time.point.cons]/3 as indicated:

    Requires: Duration2 shall be implicitly convertible to duration. Diagnostic required.

    Remarks: This constructor shall not participate in overload resolution unless Duration2 is implicitly convertible to duration.

  5. Change the following paragraphs in 23.17.6.7 [time.point.cast]:

    template <class ToDuration, class Clock, class Duration> 
      time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t);
    

    Requires Remarks: This function shall not participate in overload resolution unless ToDuration shall be is an instantiation of duration. Diagnostic required.