mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 13:26:08 +00:00
[libc++][chrono] Implements duration Rep constraints. (#80539)
Applies LWG3050 to the constraints of operator*, operator/, and operator%. The changes to the constructor were done in https://reviews.llvm.org/D118902, but that patch did not identify the related LWG-issue, and only adjusted the constructor to the wording in the Standard. Implements: - LWG 3050: Conversion specification problem in chrono::duration constructor --------- Co-authored-by: h-vetinari <h.vetinari@gmx.com>
This commit is contained in:
parent
33c6b77d2a
commit
7d9540ea96
@ -192,7 +192,7 @@
|
||||
"`1203 <https://wg21.link/LWG1203>`__","More useful rvalue stream insertion","Prague","|Complete|","12.0"
|
||||
"`2859 <https://wg21.link/LWG2859>`__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","Prague","",""
|
||||
"`3018 <https://wg21.link/LWG3018>`__","``shared_ptr``\ of function type","Prague","",""
|
||||
"`3050 <https://wg21.link/LWG3050>`__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","","","|chrono|"
|
||||
"`3050 <https://wg21.link/LWG3050>`__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","|Complete|","19.0","|chrono|"
|
||||
"`3141 <https://wg21.link/LWG3141>`__","``CopyConstructible``\ doesn't preserve source values","Prague","|Nothing to do|",""
|
||||
"`3150 <https://wg21.link/LWG3150>`__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","Prague","|Complete|","13.0","|ranges|"
|
||||
"`3175 <https://wg21.link/LWG3175>`__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","Prague","|Complete|","13.0"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -412,7 +412,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
|
||||
template <class _Rep1,
|
||||
class _Period,
|
||||
class _Rep2,
|
||||
__enable_if_t<is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
|
||||
__enable_if_t<is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||
operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
|
||||
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
|
||||
@ -423,7 +423,7 @@ operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
|
||||
template <class _Rep1,
|
||||
class _Period,
|
||||
class _Rep2,
|
||||
__enable_if_t<is_convertible<_Rep1, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
|
||||
__enable_if_t<is_convertible<const _Rep1&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||
operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) {
|
||||
return __d * __s;
|
||||
@ -435,7 +435,7 @@ template <class _Rep1,
|
||||
class _Period,
|
||||
class _Rep2,
|
||||
__enable_if_t<!__is_duration<_Rep2>::value &&
|
||||
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||
int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
|
||||
@ -457,7 +457,7 @@ template <class _Rep1,
|
||||
class _Period,
|
||||
class _Rep2,
|
||||
__enable_if_t<!__is_duration<_Rep2>::value &&
|
||||
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
|
||||
int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
|
||||
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
constexpr explicit duration(const Rep2& r,
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<Rep2, rep>::value &&
|
||||
is_convertible<const Rep2&, rep>::value &&
|
||||
(treat_as_floating_point<rep>::value ||
|
||||
!treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value)
|
||||
>::type* = 0);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define REP_H
|
||||
|
||||
#include "test_macros.h"
|
||||
#include <type_traits>
|
||||
|
||||
class Rep
|
||||
{
|
||||
@ -29,6 +30,28 @@ public:
|
||||
|
||||
struct NotARep {};
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
// Several duration operators take a Rep parameter. Before LWG3050 this
|
||||
// parameter was constrained to be convertible from a non-const object,
|
||||
// but the code always uses a const object. So the function was SFINAE'd
|
||||
// away for this type. LWG3050 fixes the constraint to use a const
|
||||
// object.
|
||||
struct RepConstConvertibleLWG3050 {
|
||||
operator long() = delete;
|
||||
operator long() const { return 2; }
|
||||
};
|
||||
namespace std {
|
||||
template <>
|
||||
struct common_type<RepConstConvertibleLWG3050, int> {
|
||||
using type = long;
|
||||
};
|
||||
template <>
|
||||
struct common_type<int, RepConstConvertibleLWG3050> {
|
||||
using type = long;
|
||||
};
|
||||
} // namespace std
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
// std::chrono:::duration has only '*', '/' and '%' taking a "Rep" parameter
|
||||
|
||||
// Multiplication is commutative, division is not.
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "truncate_fp.h"
|
||||
#include "../../rep.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
@ -65,7 +66,17 @@ int main(int, char**)
|
||||
constexpr std::chrono::duration<double, std::ratio<3, 5> > s2(5);
|
||||
static_assert(s1 / s2 == 20./3, "");
|
||||
}
|
||||
#endif
|
||||
{
|
||||
std::chrono::duration<int> d(5);
|
||||
RepConstConvertibleLWG3050 x;
|
||||
|
||||
{
|
||||
auto r = d / x;
|
||||
assert(r.count() == 2);
|
||||
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
|
||||
}
|
||||
}
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <ratio>
|
||||
#include "../../rep.h"
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
@ -60,7 +61,17 @@ int main(int, char**)
|
||||
constexpr std::chrono::duration<int, std::ratio<1, 15> > r = s1 % s2;
|
||||
static_assert(r.count() == 24, "");
|
||||
}
|
||||
#endif
|
||||
{
|
||||
std::chrono::duration<int> d(5);
|
||||
RepConstConvertibleLWG3050 x;
|
||||
|
||||
{
|
||||
auto r = d % x;
|
||||
assert(r.count() == 1);
|
||||
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
|
||||
}
|
||||
}
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,8 +26,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "../../rep.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
int main(int, char**) {
|
||||
{
|
||||
std::chrono::nanoseconds ns(3);
|
||||
ns = ns * 5;
|
||||
@ -58,7 +57,22 @@ int main(int, char**)
|
||||
d = n * d;
|
||||
assert(d.count() == 5);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
std::chrono::duration<int> d(8);
|
||||
RepConstConvertibleLWG3050 x;
|
||||
|
||||
{
|
||||
auto r = d * x;
|
||||
assert(r.count() == 16);
|
||||
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
|
||||
}
|
||||
{
|
||||
auto r = x * d;
|
||||
assert(r.count() == 16);
|
||||
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
|
||||
}
|
||||
}
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user