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.
This commit is contained in:
parent
300ef2fcc1
commit
5e9ad288eb
2 changed files with 38 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -24,8 +24,13 @@ 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 );
|
||||
|
@ -37,3 +42,24 @@ test01()
|
|||
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 );
|
||||
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() );
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue