mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-22 16:37:40 +08:00
Fix PR41130 - 'operator/ of std::chrono::duration and custom type'. Thanks to Zulan for the report, and Howard for the direction of the fix.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@357410 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1262,34 +1262,15 @@ operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d)
|
|||||||
|
|
||||||
// Duration /
|
// Duration /
|
||||||
|
|
||||||
template <class _Duration, class _Rep, bool = __is_duration<_Rep>::value>
|
|
||||||
struct __duration_divide_result
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Duration, class _Rep2,
|
|
||||||
bool = is_convertible<_Rep2,
|
|
||||||
typename common_type<typename _Duration::rep, _Rep2>::type>::value>
|
|
||||||
struct __duration_divide_imp
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Rep1, class _Period, class _Rep2>
|
|
||||||
struct __duration_divide_imp<duration<_Rep1, _Period>, _Rep2, true>
|
|
||||||
{
|
|
||||||
typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Rep1, class _Period, class _Rep2>
|
|
||||||
struct __duration_divide_result<duration<_Rep1, _Period>, _Rep2, false>
|
|
||||||
: __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Rep1, class _Period, class _Rep2>
|
template <class _Rep1, class _Period, class _Rep2>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_CONSTEXPR
|
_LIBCPP_CONSTEXPR
|
||||||
typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
|
typename enable_if
|
||||||
|
<
|
||||||
|
!__is_duration<_Rep2>::value &&
|
||||||
|
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||||
|
duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||||
|
>::type
|
||||||
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
|
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
|
||||||
{
|
{
|
||||||
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
|
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
|
||||||
@@ -1312,7 +1293,12 @@ operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2
|
|||||||
template <class _Rep1, class _Period, class _Rep2>
|
template <class _Rep1, class _Period, class _Rep2>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_CONSTEXPR
|
_LIBCPP_CONSTEXPR
|
||||||
typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
|
typename enable_if
|
||||||
|
<
|
||||||
|
!__is_duration<_Rep2>::value &&
|
||||||
|
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||||
|
duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||||
|
>::type
|
||||||
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
|
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
|
||||||
{
|
{
|
||||||
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
|
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
|
||||||
|
@@ -25,4 +25,40 @@ public:
|
|||||||
Rep& operator/=(Rep x) {data_ /= x.data_; return *this;}
|
Rep& operator/=(Rep x) {data_ /= x.data_; return *this;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is PR#41130
|
||||||
|
|
||||||
|
struct NotARep {};
|
||||||
|
|
||||||
|
// std::chrono:::duration has only '*', '/' and '%' taking a "Rep" parameter
|
||||||
|
|
||||||
|
// Multiplication is commutative, division is not.
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>
|
||||||
|
operator*(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>
|
||||||
|
operator*(NotARep, std::chrono::duration<Rep, Period> d) { return d; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>
|
||||||
|
operator/(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>
|
||||||
|
operator%(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
|
||||||
|
|
||||||
|
// op= is not commutative.
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>&
|
||||||
|
operator*=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>&
|
||||||
|
operator/=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
std::chrono::duration<Rep, Period>&
|
||||||
|
operator%=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
|
||||||
|
|
||||||
#endif // REP_H
|
#endif // REP_H
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
#if TEST_STD_VER > 14
|
#if TEST_STD_VER > 14
|
||||||
constexpr bool test_constexpr()
|
constexpr bool test_constexpr()
|
||||||
@@ -38,5 +39,14 @@ int main(int, char**)
|
|||||||
static_assert(test_constexpr(), "");
|
static_assert(test_constexpr(), "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
std::chrono::nanoseconds d(5);
|
||||||
|
NotARep n;
|
||||||
|
d /= n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
#if TEST_STD_VER > 14
|
#if TEST_STD_VER > 14
|
||||||
constexpr bool test_constexpr()
|
constexpr bool test_constexpr()
|
||||||
@@ -42,5 +43,14 @@ int main(int, char**)
|
|||||||
static_assert(test_constexpr(), "");
|
static_assert(test_constexpr(), "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
std::chrono::nanoseconds d(5);
|
||||||
|
NotARep n;
|
||||||
|
d %= n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
class NotARep {};
|
||||||
|
|
||||||
|
typedef std::chrono::seconds Duration;
|
||||||
|
Duration operator%=(Duration d, NotARep) { return d; }
|
||||||
|
|
||||||
#if TEST_STD_VER > 14
|
#if TEST_STD_VER > 14
|
||||||
constexpr bool test_constexpr()
|
constexpr bool test_constexpr()
|
||||||
{
|
{
|
||||||
@@ -38,5 +43,15 @@ int main(int, char**)
|
|||||||
static_assert(test_constexpr(), "");
|
static_assert(test_constexpr(), "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
Duration d(5);
|
||||||
|
NotARep n;
|
||||||
|
d %= n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
#if TEST_STD_VER > 14
|
#if TEST_STD_VER > 14
|
||||||
constexpr bool test_constexpr()
|
constexpr bool test_constexpr()
|
||||||
@@ -38,5 +39,14 @@ int main(int, char**)
|
|||||||
static_assert(test_constexpr(), "");
|
static_assert(test_constexpr(), "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
std::chrono::nanoseconds d(5);
|
||||||
|
NotARep n;
|
||||||
|
d *= n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,14 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::chrono::nanoseconds ns(15);
|
typedef std::chrono::nanoseconds Dur;
|
||||||
|
Dur ns(15);
|
||||||
|
ASSERT_SAME_TYPE(Dur, decltype(ns / 5));
|
||||||
ns = ns / 5;
|
ns = ns / 5;
|
||||||
assert(ns.count() == 3);
|
assert(ns.count() == 3);
|
||||||
}
|
}
|
||||||
@@ -35,5 +38,16 @@ int main(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
typedef std::chrono::nanoseconds Duration;
|
||||||
|
Duration d(5);
|
||||||
|
NotARep n;
|
||||||
|
ASSERT_SAME_TYPE(Duration, decltype(d / n));
|
||||||
|
d = d / n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,14 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::chrono::nanoseconds ns(15);
|
typedef std::chrono::nanoseconds Dur;
|
||||||
|
Dur ns(15);
|
||||||
|
ASSERT_SAME_TYPE(Dur, decltype(ns % 6));
|
||||||
ns = ns % 6;
|
ns = ns % 6;
|
||||||
assert(ns.count() == 3);
|
assert(ns.count() == 3);
|
||||||
}
|
}
|
||||||
@@ -35,5 +38,16 @@ int main(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is PR#41130
|
||||||
|
typedef std::chrono::seconds Duration;
|
||||||
|
Duration d(5);
|
||||||
|
NotARep n;
|
||||||
|
ASSERT_SAME_TYPE(Duration, decltype(d % n));
|
||||||
|
d = d % n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "../../rep.h"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
@@ -34,6 +35,7 @@ int main(int, char**)
|
|||||||
ns = 6 * ns;
|
ns = 6 * ns;
|
||||||
assert(ns.count() == 90);
|
assert(ns.count() == 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
constexpr std::chrono::nanoseconds ns(3);
|
constexpr std::chrono::nanoseconds ns(3);
|
||||||
@@ -44,5 +46,19 @@ int main(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{ // This is related to PR#41130
|
||||||
|
typedef std::chrono::nanoseconds Duration;
|
||||||
|
Duration d(5);
|
||||||
|
NotARep n;
|
||||||
|
ASSERT_SAME_TYPE(Duration, decltype(d * n));
|
||||||
|
ASSERT_SAME_TYPE(Duration, decltype(n * d));
|
||||||
|
d = d * n;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
d = n * d;
|
||||||
|
assert(d.count() == 5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user