Implement C++17 rounding functions for std::chrono (P0092R1)
* include/std/chrono (floor, ceil, round, abs): New for C++17. * testsuite/20_util/duration_cast/rounding.cc: New test. * testsuite/20_util/time_point_cast/rounding.cc: New test. * doc/xml/manual/status_cxx2017.xml: Update status table. * doc/html/manual/status.html: Regenerate. * testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust dg-error lineno. * testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise. * testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise. * testsuite/20_util/duration/literals/range.cc: Likewise. From-SVN: r239170
This commit is contained in:
parent
24bc5921a8
commit
5f6acdfb0b
@ -1,5 +1,16 @@
|
||||
2016-08-05 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/std/chrono (floor, ceil, round, abs): New for C++17.
|
||||
* testsuite/20_util/duration_cast/rounding.cc: New test.
|
||||
* testsuite/20_util/time_point_cast/rounding.cc: New test.
|
||||
* doc/xml/manual/status_cxx2017.xml: Update status table.
|
||||
* doc/html/manual/status.html: Regenerate.
|
||||
* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust
|
||||
dg-error lineno.
|
||||
* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
|
||||
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.
|
||||
* testsuite/20_util/duration/literals/range.cc: Likewise.
|
||||
|
||||
* include/std/functional (__callable_functor): Remove.
|
||||
(_Function_handler::_M_invoke): Use __invoke instead of
|
||||
__callable_functor or mem_fn.
|
||||
|
@ -606,11 +606,11 @@ Feature-testing recommendations for C++</a>.
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0185r1.html" target="_top">
|
||||
P0185R1
|
||||
</a>
|
||||
</td><td align="center"> 7 (<code class="code">__is_swappable</code> available since 6.1)</td><td align="left"><code class="code"> __cpp_lib_is_swappable >= 201603 </code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> <code class="code">is_callable</code>, the missing INVOKE related trait</td><td align="left">
|
||||
</td><td align="center"> 7 (<code class="code">__is_swappable</code> available since 6.1)</td><td align="left"><code class="code"> __cpp_lib_is_swappable >= 201603 </code></td></tr><tr><td align="left"> <code class="code">is_callable</code>, the missing INVOKE related trait</td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html" target="_top">
|
||||
P0077R2
|
||||
</a>
|
||||
</td><td align="center"> No </td><td align="left"><code class="code"> __cpp_lib_is_callable >= 201603 </code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> has_unique_object_representations </td><td align="left">
|
||||
</td><td align="center"> 7 </td><td align="left"><code class="code"> __cpp_lib_is_callable >= 201603 </code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> has_unique_object_representations </td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0258r2.html" target="_top">
|
||||
P0258R2
|
||||
</a>
|
||||
@ -618,11 +618,11 @@ Feature-testing recommendations for C++</a>.
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0181r1.html" target="_top">
|
||||
P0181R1
|
||||
</a>
|
||||
</td><td align="center"> No </td><td align="left"><code class="code"> __cpp_lib_default_order >= 201606</code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> Polishing <code class="code"><chrono></code> </td><td align="left">
|
||||
</td><td align="center"> No </td><td align="left"><code class="code"> __cpp_lib_default_order >= 201606</code></td></tr><tr><td align="left"> Polishing <code class="code"><chrono></code> </td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0092r1.html" target="_top">
|
||||
P0092R1
|
||||
</a>
|
||||
</td><td align="center"> No </td><td align="left"><code class="code"> __cpp_lib_chrono >= 201510 </code></td></tr><tr><td align="left"> Integrating <code class="code">std::string_view</code> and <code class="code">std::string</code> </td><td align="left">
|
||||
</td><td align="center"> 7 </td><td align="left"><code class="code"> __cpp_lib_chrono >= 201510 </code></td></tr><tr><td align="left"> Integrating <code class="code">std::string_view</code> and <code class="code">std::string</code> </td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0254r2.pdf" target="_top">
|
||||
P0254R2
|
||||
</a>
|
||||
|
@ -437,14 +437,13 @@ Feature-testing recommendations for C++</link>.
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<?dbhtml bgcolor="#C8B0B0" ?>
|
||||
<entry> Polishing <code><chrono></code> </entry>
|
||||
<entry>
|
||||
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0092r1.html">
|
||||
P0092R1
|
||||
</link>
|
||||
</entry>
|
||||
<entry align="center"> No </entry>
|
||||
<entry align="center"> 7 </entry>
|
||||
<entry><code> __cpp_lib_chrono >= 201510 </code></entry>
|
||||
</row>
|
||||
|
||||
|
@ -208,11 +208,69 @@ _GLIBCXX_END_NAMESPACE_VERSION
|
||||
struct treat_as_floating_point
|
||||
: is_floating_point<_Rep>
|
||||
{ };
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template <typename _Rep>
|
||||
constexpr bool treat_as_floating_point_v =
|
||||
treat_as_floating_point<_Rep>::value;
|
||||
#endif // C++17
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
# define __cpp_lib_chrono 201510
|
||||
|
||||
template<typename _ToDur, typename _Rep, typename _Period>
|
||||
constexpr enable_if_t<__is_duration<_ToDur>::value, _ToDur>
|
||||
floor(const duration<_Rep, _Period>& __d)
|
||||
{
|
||||
auto __to = chrono::duration_cast<_ToDur>(__d);
|
||||
if (__to > __d)
|
||||
--__to;
|
||||
return __to;
|
||||
}
|
||||
|
||||
template<typename _ToDur, typename _Rep, typename _Period>
|
||||
constexpr enable_if_t<__is_duration<_ToDur>::value, _ToDur>
|
||||
ceil(const duration<_Rep, _Period>& __d)
|
||||
{
|
||||
auto __to = chrono::duration_cast<_ToDur>(__d);
|
||||
if (__to < __d)
|
||||
return __to + _ToDur{1};
|
||||
return __to;
|
||||
}
|
||||
|
||||
template <typename _ToDur, typename _Rep, typename _Period>
|
||||
constexpr enable_if_t<
|
||||
__and_<__is_duration<_ToDur>,
|
||||
__not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
|
||||
_ToDur>
|
||||
round(const duration<_Rep, _Period>& __d)
|
||||
{
|
||||
_ToDur __t0 = chrono::floor<_ToDur>(__d);
|
||||
_ToDur __t1 = __t0 + _ToDur{1};
|
||||
auto __diff0 = __d - __t0;
|
||||
auto __diff1 = __t1 - __d;
|
||||
if (__diff0 == __diff1)
|
||||
{
|
||||
if (__t0.count() & 1)
|
||||
return __t1;
|
||||
return __t0;
|
||||
}
|
||||
else if (__diff0 < __diff1)
|
||||
return __t0;
|
||||
return __t1;
|
||||
}
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
constexpr
|
||||
enable_if_t<numeric_limits<_Rep>::is_signed, duration<_Rep, _Period>>
|
||||
abs(duration<_Rep, _Period> __d)
|
||||
{
|
||||
if (__d >= __d.zero())
|
||||
return __d;
|
||||
return -__d;
|
||||
}
|
||||
#endif // C++17
|
||||
|
||||
/// duration_values
|
||||
template<typename _Rep>
|
||||
struct duration_values
|
||||
@ -610,6 +668,37 @@ _GLIBCXX_END_NAMESPACE_VERSION
|
||||
return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
|
||||
}
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template<typename _ToDur, typename _Clock, typename _Dur>
|
||||
constexpr
|
||||
enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
|
||||
floor(const time_point<_Clock, _Dur>& __tp)
|
||||
{
|
||||
return time_point<_Clock, _ToDur>{
|
||||
chrono::floor<_ToDur>(__tp.time_since_epoch())};
|
||||
}
|
||||
|
||||
template<typename _ToDur, typename _Clock, typename _Dur>
|
||||
constexpr
|
||||
enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
|
||||
ceil(const time_point<_Clock, _Dur>& __tp)
|
||||
{
|
||||
return time_point<_Clock, _ToDur>{
|
||||
chrono::ceil<_ToDur>(__tp.time_since_epoch())};
|
||||
}
|
||||
|
||||
template<typename _ToDur, typename _Clock, typename _Dur>
|
||||
constexpr enable_if_t<
|
||||
__and_<__is_duration<_ToDur>,
|
||||
__not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
|
||||
time_point<_Clock, _ToDur>>
|
||||
round(const time_point<_Clock, _Dur>& __tp)
|
||||
{
|
||||
return time_point<_Clock, _ToDur>{
|
||||
chrono::round<_ToDur>(__tp.time_since_epoch())};
|
||||
}
|
||||
#endif // C++17
|
||||
|
||||
template<typename _Clock, typename _Dur1,
|
||||
typename _Rep2, typename _Period2>
|
||||
constexpr time_point<_Clock,
|
||||
|
@ -27,5 +27,5 @@ test01()
|
||||
|
||||
// std::numeric_limits<int64_t>::max() == 9223372036854775807;
|
||||
auto h = 9223372036854775808h;
|
||||
// { dg-error "cannot be represented" "" { target *-*-* } 800 }
|
||||
// { dg-error "cannot be represented" "" { target *-*-* } 889 }
|
||||
}
|
||||
|
@ -31,5 +31,5 @@ void test01()
|
||||
test_type d;
|
||||
}
|
||||
|
||||
// { dg-error "rep cannot be a duration" "" { target *-*-* } 250 }
|
||||
// { dg-error "rep cannot be a duration" "" { target *-*-* } 308 }
|
||||
// { dg-error "required from here" "" { target *-*-* } 31 }
|
||||
|
@ -32,5 +32,5 @@ void test01()
|
||||
test_type d; // { dg-error "required from here" }
|
||||
}
|
||||
|
||||
// { dg-error "must be a specialization of ratio" "" { target *-*-* } 251 }
|
||||
// { dg-error "must be a specialization of ratio" "" { target *-*-* } 309 }
|
||||
// { dg-prune-output "not a member" }
|
||||
|
@ -33,4 +33,4 @@ void test01()
|
||||
test_type d; // { dg-error "required from here" }
|
||||
}
|
||||
|
||||
// { dg-error "period must be positive" "" { target *-*-* } 253 }
|
||||
// { dg-error "period must be positive" "" { target *-*-* } 311 }
|
||||
|
57
libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc
Normal file
57
libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile }
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#if __cpp_lib_chrono < 201510
|
||||
# error "__cpp_lib_chrono < 201510"
|
||||
#endif
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using std::chrono::seconds;
|
||||
|
||||
static_assert( std::chrono::floor<seconds>(1000ms) == 1s );
|
||||
static_assert( std::chrono::floor<seconds>(1001ms) == 1s );
|
||||
static_assert( std::chrono::floor<seconds>(1500ms) == 1s );
|
||||
static_assert( std::chrono::floor<seconds>(1999ms) == 1s );
|
||||
static_assert( std::chrono::floor<seconds>(2000ms) == 2s );
|
||||
static_assert( std::chrono::floor<seconds>(2001ms) == 2s );
|
||||
static_assert( std::chrono::floor<seconds>(2500ms) == 2s );
|
||||
|
||||
static_assert( std::chrono::ceil<seconds>(1000ms) == 1s );
|
||||
static_assert( std::chrono::ceil<seconds>(1001ms) == 2s );
|
||||
static_assert( std::chrono::ceil<seconds>(1500ms) == 2s );
|
||||
static_assert( std::chrono::ceil<seconds>(1999ms) == 2s );
|
||||
static_assert( std::chrono::ceil<seconds>(2000ms) == 2s );
|
||||
static_assert( std::chrono::ceil<seconds>(2001ms) == 3s );
|
||||
static_assert( std::chrono::ceil<seconds>(2500ms) == 3s );
|
||||
|
||||
static_assert( std::chrono::round<seconds>(1000ms) == 1s );
|
||||
static_assert( std::chrono::round<seconds>(1001ms) == 1s );
|
||||
static_assert( std::chrono::round<seconds>(1499ms) == 1s );
|
||||
static_assert( std::chrono::round<seconds>(1500ms) == 2s );
|
||||
static_assert( std::chrono::round<seconds>(1999ms) == 2s );
|
||||
static_assert( std::chrono::round<seconds>(2000ms) == 2s );
|
||||
static_assert( std::chrono::round<seconds>(2001ms) == 2s );
|
||||
static_assert( std::chrono::round<seconds>(2500ms) == 2s );
|
||||
static_assert( std::chrono::round<seconds>(2501ms) == 3s );
|
||||
|
||||
static_assert( std::chrono::abs(100ms) == 100ms );
|
||||
static_assert( std::chrono::abs(-100ms) == 100ms );
|
59
libstdc++-v3/testsuite/20_util/time_point_cast/rounding.cc
Normal file
59
libstdc++-v3/testsuite/20_util/time_point_cast/rounding.cc
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile }
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#if __cpp_lib_chrono < 201510
|
||||
# error "__cpp_lib_chrono < 201510"
|
||||
#endif
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
constexpr std::chrono::system_clock::time_point base{};
|
||||
|
||||
static_assert( std::chrono::floor<seconds>(base + 1000ms) == (base + 1s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 1001ms) == (base + 1s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 1500ms) == (base + 1s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 1999ms) == (base + 1s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 2000ms) == (base + 2s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 2001ms) == (base + 2s) );
|
||||
static_assert( std::chrono::floor<seconds>(base + 2500ms) == (base + 2s) );
|
||||
|
||||
static_assert( std::chrono::ceil<seconds>(base + 1000ms) == (base + 1s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 1001ms) == (base + 2s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 1500ms) == (base + 2s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 1999ms) == (base + 2s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 2000ms) == (base + 2s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 2001ms) == (base + 3s) );
|
||||
static_assert( std::chrono::ceil<seconds>(base + 2500ms) == (base + 3s) );
|
||||
|
||||
static_assert( std::chrono::round<seconds>(base + 1000ms) == (base + 1s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 1001ms) == (base + 1s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 1499ms) == (base + 1s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 1500ms) == (base + 2s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 1999ms) == (base + 2s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 2000ms) == (base + 2s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 2001ms) == (base + 2s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 2500ms) == (base + 2s) );
|
||||
static_assert( std::chrono::round<seconds>(base + 2501ms) == (base + 3s) );
|
Loading…
Reference in New Issue
Block a user