Boost logo

Boost-Commit :

From: hinnant_at_[hidden]
Date: 2007-12-29 15:54:09


Author: hinnant
Date: 2007-12-29 15:54:09 EST (Sat, 29 Dec 2007)
New Revision: 42347
URL: http://svn.boost.org/trac/boost/changeset/42347

Log:
V1 issue 63.

Text files modified:
   sandbox/committee/LWG/issues.html | 86 +++++++
   sandbox/committee/LWG/ref_impl/hdate_time | 467 +++++++++------------------------------
   2 files changed, 202 insertions(+), 351 deletions(-)

Modified: sandbox/committee/LWG/issues.html
==============================================================================
--- sandbox/committee/LWG/issues.html (original)
+++ sandbox/committee/LWG/issues.html 2007-12-29 15:54:09 EST (Sat, 29 Dec 2007)
@@ -384,6 +384,92 @@
 But <code>d</code> can't be <code>const</code>. It is used in a non-<code>const</code> manner.
 </p>
 
+<p>
+&#9998; 63. [time.duration.requirements] says in part:
+</p>
+
+<blockquote>
+... The resolution of <code>E</code> shall not be finer than the resolution of <code>D</code> (diagnostic required).
+</blockquote>
+
+<p>
+This wording works fine for the std-defined durations. Each duration that has courser resolution than
+another is <em>exactly convertible</em> to that other duration of finer resolution. However for
+user-defined durations, having a courser resolution than some std-defined duration is no guarantee
+that the user-defined duration is exactly convertible to the finer std-defined duration. For
+example consider a user-defined duration that has <code>ticks_per_second = 30</code>. The
+following example compiles with the current wording:
+</p>
+
+<blockquote><pre>
+std::milliseconds ms;
+frame_time_duration ft = 1;
+ms += ft; // ms.count() == 33
+</pre></blockquote>
+
+<p>
+However 33 milliseconds is not exactly 1/30 of a second. This is an inexact conversion, arbitrarily
+coded with truncation as opposed to round-up, or round-to-nearest.
+</p>
+<p>
+I propose that we change the requirement on <code>E</code> from "not finer than" to "exactly
+convertible to" which matches the original intent. A new <code>&lt;hdate_time&gt;</code> has
+been checked in which demonstrates this change is implementable. However I have not yet updated
+the paper (pending discussion) with:
+</p>
+
+<blockquote>
+... The resolution of <code>E</code> shall <del>not</del> be <del>finer than</del>
+<ins>exactly convertible to</ins> the resolution of <code>D</code> (diagnostic required).
+</blockquote>
+
+<p>
+If need be we can precisely define <i>exactly convertible</i> as:
+</p>
+
+<blockquote>
+<p>
+The duration <code>E</code> is <i>exactly convertible</i> to <code>D</code> if
+</p>
+
+<ul>
+<li>
+<code>E::is_subsecond</code> is <code>false</code> and <code>D::is_subsecond</code>
+is <code>true</code>, or
+</li>
+<li>
+<code>E::is_subsecond</code> is <code>false</code> and <code>D::is_subsecond</code>
+is <code>false</code>, and <code>E::seconds_per_tick % D::seconds_per_tick == 0</code>, or
+</li>
+<li>
+<code>E::is_subsecond</code> is <code>true</code> and <code>D::is_subsecond</code>
+is <code>true</code>, and <code>D::ticks_per_second % E::ticks_per_second == 0</code>.
+</li>
+</ul>
+
+<p>
+Otherwise the duration <code>E</code> is not exactly convertible to <code>D</code>.
+</p>
+
+</blockquote>
+
+<p>
+This change would make the above code fail to compile:
+</p>
+
+<blockquote><pre>
+std::milliseconds ms;
+frame_time_duration ft = 1;
+ms += ft;
+
+error: no match for ‘operator+=’ in ‘ms += ft’
+</pre></blockquote>
+
+<p>
+However if <code>frame_time_duration::ticks_per_second</code> is changed to 40, the example now compiles
+since 25 milliseconds is exactly equal to 1/40 of a second.
+</p>
+
 </body>
 
 </html>

Modified: sandbox/committee/LWG/ref_impl/hdate_time
==============================================================================
--- sandbox/committee/LWG/ref_impl/hdate_time (original)
+++ sandbox/committee/LWG/ref_impl/hdate_time 2007-12-29 15:54:09 EST (Sat, 29 Dec 2007)
@@ -286,6 +286,8 @@
 
 namespace std {
 
+// __is_duration
+
 template <class T>
 class __has_tick_type
 {
@@ -309,40 +311,19 @@
         static const bool value = sizeof(test<T>(0)) == 1;
 };
 
-template <class T>
+template <class T, bool = stb::is_class<T>::value>
 class __is_duration
 {
 public:
         static const bool value = __has_tick_type<T>::value &&
- __has_get_count<T>::value &&
- stb::is_convertible<long long, T>::value;
-};
-
-// __compare_resolution
-
-template <class LhsDuration, class RhsDuration,
- bool = LhsDuration::is_subsecond, bool = RhsDuration::is_subsecond>
-struct __compare_resolution // <LhsDuration, RhsDuration, true, true>
-{
- static const bool value = LhsDuration::ticks_per_second >= RhsDuration::ticks_per_second;
+ __has_get_count<T>::value;
 };
 
-template <class LhsDuration, class RhsDuration>
-struct __compare_resolution<LhsDuration, RhsDuration, true, false>
-{
- static const bool value = true;
-};
-
-template <class LhsDuration, class RhsDuration>
-struct __compare_resolution<LhsDuration, RhsDuration, false, true>
-{
- static const bool value = false;
-};
-
-template <class LhsDuration, class RhsDuration>
-struct __compare_resolution<LhsDuration, RhsDuration, false, false>
+template <class T>
+class __is_duration<T, false>
 {
- static const bool value = LhsDuration::seconds_per_tick <= RhsDuration::seconds_per_tick;
+public:
+ static const bool value = false;
 };
 
 // __duration_cast
@@ -422,322 +403,149 @@
                                                integral_constant<bool, FromDuration::is_subsecond>());
 }
 
-// Durations
-
-class nanoseconds
-{
-public:
- typedef long long tick_type;
-private:
- tick_type ns_;
-public:
- nanoseconds(long long ns = 0) : ns_(ns) {}
-
- // traits information
- static const tick_type ticks_per_second = 1000L * 1000 * 1000;
- static const tick_type seconds_per_tick = 0;
- static const bool is_subsecond = seconds_per_tick == 0;
+// __is_duration_exactly_convertible
 
- // + common functions
+template <class FromDuration, class ToDuration, bool FromSubSecond, bool ToSubSecond>
+struct __is_duration_exactly_convertible_imp;
 
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<nanoseconds, RhsDuration>::value,
- nanoseconds&
- >::type
- operator-=(const RhsDuration& d)
- {
- ns_ -= __duration_cast<nanoseconds>(d).count();
- return *this;
- }
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<nanoseconds, RhsDuration>::value,
- nanoseconds&
- >::type
- operator+=(const RhsDuration& d)
- {
- ns_ += __duration_cast<nanoseconds>(d).count();
- return *this;
- }
-
- nanoseconds operator-() const {return -ns_;}
-
- nanoseconds& operator*=(long rhs) {ns_ *= rhs; return *this;}
- nanoseconds& operator/=(long divisor) {ns_ /= divisor; return *this;}
-
- tick_type count() const {return ns_;}
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible_imp<FromDuration, ToDuration, true, true>
+{
+ static const bool value = ToDuration::ticks_per_second % FromDuration::ticks_per_second == 0;
+// static const bool value = ToDuration::ticks_per_second >= FromDuration::ticks_per_second;
 };
 
-class microseconds
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible_imp<FromDuration, ToDuration, false, true>
 {
-public:
- typedef long long tick_type;
-private:
- tick_type us_;
-public:
- microseconds(long long us = 0) : us_(us) {}
-
- // traits information
- static const tick_type ticks_per_second = 1000L * 1000;
- static const tick_type seconds_per_tick = 0;
- static const bool is_subsecond = seconds_per_tick == 0;
-
- // conversions
- operator nanoseconds() const {return __duration_cast<nanoseconds>(*this);}
-
- // + common functions
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<microseconds, RhsDuration>::value,
- microseconds&
- >::type
- operator-=(const RhsDuration& d)
- {
- us_ -= __duration_cast<microseconds>(d).count();
- return *this;
- }
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<microseconds, RhsDuration>::value,
- microseconds&
- >::type
- operator+=(const RhsDuration& d)
- {
- us_ += __duration_cast<microseconds>(d).count();
- return *this;
- }
-
- microseconds operator-() const {return -us_;}
-
- microseconds& operator*=(long rhs) {us_ *= rhs; return *this;}
- microseconds& operator/=(long divisor) {us_ /= divisor; return *this;}
-
- tick_type count() const {return us_;}
+ static const bool value = true;
 };
 
-class milliseconds
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible_imp<FromDuration, ToDuration, true, false>
 {
-public:
- typedef long long tick_type;
-private:
- tick_type ms_;
-public:
- milliseconds(long long ms = 0) : ms_(ms) {}
-
- // traits information
- static const tick_type ticks_per_second = 1000;
- static const tick_type seconds_per_tick = 0;
- static const bool is_subsecond = seconds_per_tick == 0;
-
- // conversions
- operator nanoseconds() const {return __duration_cast<nanoseconds>(*this);}
- operator microseconds() const {return __duration_cast<microseconds>(*this);}
-
- // + common functions
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<milliseconds, RhsDuration>::value,
- milliseconds&
- >::type
- operator-=(const RhsDuration& d)
- {
- ms_ -= __duration_cast<milliseconds>(d).count();
- return *this;
- }
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<milliseconds, RhsDuration>::value,
- milliseconds&
- >::type
- operator+=(const RhsDuration& d)
- {
- ms_ += __duration_cast<milliseconds>(d).count();
- return *this;
- }
-
- milliseconds operator-() const {return -ms_;}
-
- milliseconds& operator*=(long rhs) {ms_ *= rhs; return *this;}
- milliseconds& operator/=(long divisor) {ms_ /= divisor; return *this;}
-
- tick_type count() const {return ms_;}
+ static const bool value = false;
 };
 
-class seconds
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible_imp<FromDuration, ToDuration, false, false>
 {
-public:
- typedef long long tick_type;
-private:
- tick_type s_;
-public:
- seconds(long long s = 0) : s_(s) {}
-
- // traits information
- static const tick_type ticks_per_second = 1;
- static const tick_type seconds_per_tick = 1;
- static const bool is_subsecond = seconds_per_tick == 0;
-
- // conversions
- operator nanoseconds() const {return __duration_cast<nanoseconds>(*this);}
- operator microseconds() const {return __duration_cast<microseconds>(*this);}
- operator milliseconds() const {return __duration_cast<milliseconds>(*this);}
-
- // + common functions
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<seconds, RhsDuration>::value,
- seconds&
- >::type
- operator-=(const RhsDuration& d)
- {
- s_ -= __duration_cast<seconds>(d).count();
- return *this;
- }
-
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<seconds, RhsDuration>::value,
- seconds&
- >::type
- operator+=(const RhsDuration& d)
- {
- s_ += __duration_cast<seconds>(d).count();
- return *this;
- }
-
- seconds operator-() const {return -s_;}
-
- seconds& operator*=(long rhs) {s_ *= rhs; return *this;}
- seconds& operator/=(long divisor) {s_ /= divisor; return *this;}
-
-
- tick_type count() const {return s_;}
+ static const bool value = FromDuration::seconds_per_tick % ToDuration::seconds_per_tick == 0;
+// static const bool value = FromDuration::seconds_per_tick >= ToDuration::seconds_per_tick;
 };
 
-class minutes
+template <class FromDuration, class ToDuration, bool BothDurations>
+struct __is_duration_exactly_convertible_imp_imp
 {
-public:
- typedef long tick_type;
-private:
- tick_type mn_;
-public:
- minutes(long long mn = 0) : mn_(static_cast<tick_type>(mn)) {}
-
- // traits information
- static const tick_type ticks_per_second = 0;
- static const tick_type seconds_per_tick = 60;
- static const bool is_subsecond = seconds_per_tick == 0;
+ static const bool value = false;
+};
 
- // conversions
- operator nanoseconds() const {return __duration_cast<nanoseconds>(*this);}
- operator microseconds() const {return __duration_cast<microseconds>(*this);}
- operator milliseconds() const {return __duration_cast<milliseconds>(*this);}
- operator seconds() const {return __duration_cast<seconds>(*this);}
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible_imp_imp<FromDuration, ToDuration, true>
+{
+ static const bool value = __is_duration_exactly_convertible_imp<FromDuration, ToDuration,
+ FromDuration::is_subsecond, ToDuration::is_subsecond>::value;
+};
 
- // + common functions
+template <class FromDuration, class ToDuration>
+struct __is_duration_exactly_convertible
+{
+ static const bool value = __is_duration_exactly_convertible_imp_imp<FromDuration, ToDuration,
+ __is_duration<FromDuration>::value &&
+ __is_duration<ToDuration>::value>::value;
+};
 
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<minutes, RhsDuration>::value,
- minutes&
- >::type
- operator-=(const RhsDuration& d)
- {
- mn_ -= __duration_cast<minutes>(d).count();
- return *this;
- }
+// __choose_duration
 
- template<typename RhsDuration>
- typename enable_if
- <
- __compare_resolution<minutes, RhsDuration>::value,
- minutes&
- >::type
- operator+=(const RhsDuration& d)
- {
- mn_ += __duration_cast<minutes>(d).count();
- return *this;
- }
+template <class LhsDuration, class RhsDuration,
+ bool = __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
+ bool = __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value>
+struct __choose_duration
+{
+};
 
- minutes operator-() const {return -mn_;}
+template <class LhsDuration, class RhsDuration>
+struct __choose_duration<LhsDuration, RhsDuration, true, true>
+{
+ typedef LhsDuration type;
+};
 
- minutes& operator*=(long rhs) {mn_ *= rhs; return *this;}
- minutes& operator/=(long divisor) {mn_ /= divisor; return *this;}
+template <class LhsDuration, class RhsDuration>
+struct __choose_duration<LhsDuration, RhsDuration, true, false>
+{
+ typedef LhsDuration type;
+};
 
- tick_type count() const {return mn_;}
+template <class LhsDuration, class RhsDuration>
+struct __choose_duration<LhsDuration, RhsDuration, false, true>
+{
+ typedef RhsDuration type;
 };
 
-class hours
+// Durations
+
+template <class TickType, TickType TicksPerSecond, TickType SecondsPerTick>
+class __basic_duration
 {
 public:
- typedef long tick_type;
+ typedef TickType tick_type;
 private:
- tick_type hr_;
+ tick_type tick_;
 public:
- hours(long long hr = 0) : hr_(static_cast<tick_type>(hr)) {}
+ __basic_duration(long long tick = 0) : tick_(tick) {}
 
     // traits information
- static const tick_type ticks_per_second = 0;
- static const tick_type seconds_per_tick = 3600;
+ static const tick_type ticks_per_second = TicksPerSecond;
+ static const tick_type seconds_per_tick = SecondsPerTick;
     static const bool is_subsecond = seconds_per_tick == 0;
 
     // conversions
- operator nanoseconds() const {return __duration_cast<nanoseconds>(*this);}
- operator microseconds() const {return __duration_cast<microseconds>(*this);}
- operator milliseconds() const {return __duration_cast<milliseconds>(*this);}
- operator seconds() const {return __duration_cast<seconds>(*this);}
- operator minutes() const {return __duration_cast<minutes>(*this);}
+ template <class RhsDuration>
+ __basic_duration(const RhsDuration& d,
+ typename enable_if<__is_duration_exactly_convertible<RhsDuration, __basic_duration>::value>::type* = 0)
+ : tick_(__duration_cast<__basic_duration>(d).count()) {}
 
     // + common functions
 
     template<typename RhsDuration>
         typename enable_if
         <
- __compare_resolution<hours, RhsDuration>::value,
- hours&
+ __is_duration_exactly_convertible<RhsDuration, __basic_duration>::value,
+ __basic_duration&
>::type
         operator-=(const RhsDuration& d)
         {
- hr_ -= __duration_cast<hours>(d).count();
+ tick_ -= __duration_cast<__basic_duration>(d).count();
             return *this;
         }
 
     template<typename RhsDuration>
         typename enable_if
         <
- __compare_resolution<hours, RhsDuration>::value,
- hours&
+ __is_duration_exactly_convertible<RhsDuration, __basic_duration>::value,
+ __basic_duration&
>::type
         operator+=(const RhsDuration& d)
         {
- hr_ += __duration_cast<hours>(d).count();
+ tick_ += __duration_cast<__basic_duration>(d).count();
             return *this;
         }
 
- hours operator-() const {return -hr_;}
+ __basic_duration operator-() const {return __basic_duration(-tick_);}
 
- hours& operator*=(long rhs) {hr_ *= rhs; return *this;}
- hours& operator/=(long divisor) {hr_ /= divisor; return *this;}
+ __basic_duration& operator*=(long rhs) {tick_ *= rhs; return *this;}
+ __basic_duration& operator/=(long divisor) {tick_ /= divisor; return *this;}
 
- tick_type count() const {return hr_;}
+ tick_type count() const {return tick_;}
 };
 
+typedef __basic_duration<long long, 1000L * 1000 * 1000, 0> nanoseconds;
+typedef __basic_duration<long long, 1000L * 1000, 0> microseconds;
+typedef __basic_duration<long long, 1000, 0> milliseconds;
+typedef __basic_duration<long long, 1, 1> seconds;
+typedef __basic_duration<long, 0, 60> minutes;
+typedef __basic_duration<long, 0, 3600> hours;
+
 // Duration ==
 
 template <class LhsDuration, class RhsDuration>
@@ -760,13 +568,13 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator==(const LhsDuration& lhs, const RhsDuration& rhs)
 {
- return __duration_eq(lhs, rhs, integral_constant<bool, __compare_resolution<LhsDuration, RhsDuration>::value>());
+ return __duration_eq(lhs, rhs, integral_constant<bool, __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value>());
 }
 
 // Duration !=
@@ -775,8 +583,8 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator!=(const LhsDuration& lhs, const RhsDuration& rhs)
@@ -806,13 +614,13 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator< (const LhsDuration& lhs, const RhsDuration& rhs)
 {
- return __duration_lt(lhs, rhs, integral_constant<bool, __compare_resolution<LhsDuration, RhsDuration>::value>());
+ return __duration_lt(lhs, rhs, integral_constant<bool, __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value>());
 }
 
 // Duration >
@@ -821,8 +629,8 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator> (const LhsDuration& lhs, const RhsDuration& rhs)
@@ -836,8 +644,8 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator<=(const LhsDuration& lhs, const RhsDuration& rhs)
@@ -851,8 +659,8 @@
 inline
 typename enable_if
 <
- __is_duration<LhsDuration>::value &&
- __is_duration<RhsDuration>::value,
+ __is_duration_exactly_convertible<LhsDuration, RhsDuration>::value ||
+ __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value,
     bool
>::type
 operator>=(const LhsDuration& lhs, const RhsDuration& rhs)
@@ -860,54 +668,11 @@
     return !(lhs < rhs);
 }
 
-
-template <class LhsDuration, class RhsDuration, bool = __compare_resolution<LhsDuration, RhsDuration>::value>
-struct __compute_promotion
-{
- typedef LhsDuration type;
-};
-
-template <class LhsDuration, class RhsDuration>
-struct __compute_promotion<LhsDuration, RhsDuration, false>
-{
- typedef RhsDuration type;
-};
-
-template <bool, class U>
-struct __short_circut_and_imp
-{
- static const bool value = U::value;
-};
-
-template <class U>
-struct __short_circut_and_imp<false, U>
-{
- static const bool value = false;
-};
-
-template <class T, class U>
-struct __short_circut_and
-{
- static const bool value = __short_circut_and_imp<T::value, U>::value;
-};
-
-template <class LhsDuration, class RhsDuration, bool = __short_circut_and<__is_duration<RhsDuration>,
- __is_duration<LhsDuration>>::value>
-struct __promote_duration
-{
-};
-
-template <class LhsDuration, class RhsDuration>
-struct __promote_duration<LhsDuration, RhsDuration, true>
-{
- typedef typename __compute_promotion<LhsDuration, RhsDuration>::type type;
-};
-
 // Duration +
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 __duration_plus(const LhsDuration& lhs, const RhsDuration& rhs, true_type)
 {
     LhsDuration r(lhs);
@@ -917,7 +682,7 @@
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 __duration_plus(const LhsDuration& lhs, const RhsDuration& rhs, false_type)
 {
     RhsDuration r(rhs);
@@ -927,17 +692,17 @@
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 operator+(const LhsDuration& lhs, const RhsDuration& rhs)
 {
- return __duration_plus(lhs, rhs, integral_constant<bool, __compare_resolution<LhsDuration, RhsDuration>::value>());
+ return __duration_plus(lhs, rhs, integral_constant<bool, __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value>());
 }
 
 // Duration -
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 __duration_subtract(const LhsDuration& lhs, const RhsDuration& rhs, true_type)
 {
     LhsDuration r(lhs);
@@ -947,7 +712,7 @@
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 __duration_subtract(const LhsDuration& lhs, const RhsDuration& rhs, false_type)
 {
     RhsDuration r = __duration_cast<RhsDuration>(lhs);
@@ -957,10 +722,10 @@
 
 template <class LhsDuration, class RhsDuration>
 inline
-typename __promote_duration<LhsDuration, RhsDuration>::type
+typename __choose_duration<LhsDuration, RhsDuration>::type
 operator-(const LhsDuration& lhs, const RhsDuration& rhs)
 {
- return __duration_subtract(lhs, rhs, integral_constant<bool, __compare_resolution<LhsDuration, RhsDuration>::value>());
+ return __duration_subtract(lhs, rhs, integral_constant<bool, __is_duration_exactly_convertible<RhsDuration, LhsDuration>::value>());
 }
 
 // Duration *


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk