diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-08-20 19:41:15 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-08-20 19:42:02 +0100 |
commit | 5e9ad288eb6fb366142b166e7985d16727b398e1 (patch) | |
tree | 1e33902007eeb2e36356927ce6de9ddef61e2deb | |
parent | 300ef2fcc10e98359d14654be23bbb84a5d141e1 (diff) | |
download | gcc-5e9ad288eb6fb366142b166e7985d16727b398e1.zip gcc-5e9ad288eb6fb366142b166e7985d16727b398e1.tar.gz gcc-5e9ad288eb6fb366142b166e7985d16727b398e1.tar.bz2 |
libstdc++: Make incrementable<__int128> satisfied in strict mode
This adds specializations of std::incrementable_traits so that 128-bit
integers are always considered incrementable (and therefore usable with
std::ranges::iota_view) even when they don't satisfy std::integral.
libstdc++-v3/ChangeLog:
* include/bits/iterator_concepts.h [__STRICT_ANSI__]
(incrementable_traits<__int128>): Define specialization.
(incrementable_traits<unsigned __int128>): Likewise.
* testsuite/std/ranges/iota/96042.cc: Test iota_view with
__int128.
-rw-r--r-- | libstdc++-v3/include/bits/iterator_concepts.h | 11 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/iota/96042.cc | 28 |
2 files changed, 38 insertions, 1 deletions
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index 5033f2b..bd6660c 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -173,6 +173,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>; }; +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // __int128 is incrementable even if !integral<__int128> + template<> + struct incrementable_traits<__int128> + { using difference_type = __int128; }; + + template<> + struct incrementable_traits<unsigned __int128> + { using difference_type = __int128; }; +#endif + namespace __detail { // An iterator such that iterator_traits<_Iter> names a specialization diff --git a/libstdc++-v3/testsuite/std/ranges/iota/96042.cc b/libstdc++-v3/testsuite/std/ranges/iota/96042.cc index 6f5c8f6..911663b 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/96042.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/96042.cc @@ -24,8 +24,33 @@ void test01() { // PR libstdc++/96042 - using V = std::ranges::iota_view<long long, int>; + using V = std::ranges::iota_view<long long, long long>; + + // In strict -std=c++20 mode there is no integer wider than long long, + // so V's difference type is an integer-class type, [iterator.concept.winc]. + // In practice this is either __int128 or __detail::__max_diff_type. using D = std::ranges::range_difference_t<V>; + // Ensure that numeric_limits is correctly specialized for the type. + using L = std::numeric_limits<D>; + static_assert( L::is_specialized ); + static_assert( L::is_signed ); + static_assert( L::is_integer ); + static_assert( L::is_exact ); + static_assert( L::digits > std::numeric_limits<long long>::digits ); + static_assert( L::digits10 == static_cast<int>(L::digits * 0.30103) ); + static_assert( L::min() == (D(1) << L::digits) ); + static_assert( L::max() == ~L::min() ); + static_assert( L::lowest() == L::min() ); +} + +#ifdef __SIZEOF_INT128__ +void +test02() +{ + // When the target supports __int128 it can be used in iota_view + // even in strict mode where !integral<__int128>. + using V = std::ranges::iota_view<__int128, __int128>; + using D = std::ranges::range_difference_t<V>; // __detail::__max_diff_type using L = std::numeric_limits<D>; static_assert( L::is_specialized ); static_assert( L::is_signed ); @@ -37,3 +62,4 @@ test01() static_assert( L::max() == ~L::min() ); static_assert( L::lowest() == L::min() ); } +#endif |