libstdc++: Make byte-sized std::fill_n a constant expression (PR 94933)
The overload for byte types uses memset and isn't constexpr. This adds the specifier and uses std::is_constant_evaluated() to provide a compile-time alternative. PR libstdc++/94933 * include/bits/stl_algobase.h (__fill_a1): Make overload for byte types usable in constant expressions. * testsuite/25_algorithms/fill_n/constexpr.cc: Test with bytes and non-scalars.
This commit is contained in:
parent
18a6e4130f
commit
22b6b5d6cf
|
@ -1,3 +1,11 @@
|
|||
2020-05-03 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/94933
|
||||
* include/bits/stl_algobase.h (__fill_a1): Make overload for byte types
|
||||
usable in constant expressions.
|
||||
* testsuite/25_algorithms/fill_n/constexpr.cc: Test with bytes and
|
||||
non-scalars.
|
||||
|
||||
2020-05-01 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/94901
|
||||
|
|
|
@ -875,11 +875,20 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
|
|||
|
||||
// Specialization: for char types we can use memset.
|
||||
template<typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline typename
|
||||
__gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type
|
||||
__fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c)
|
||||
{
|
||||
const _Tp __tmp = __c;
|
||||
#if __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated())
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
*__first = __tmp;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (const size_t __len = __last - __first)
|
||||
__builtin_memset(__first, static_cast<unsigned char>(__tmp), __len);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,37 @@ test()
|
|||
|
||||
const auto outd = std::fill_n(ma0.begin(), 6, 77);
|
||||
|
||||
return outd == ma0.begin() + 6;
|
||||
return outd == ma0.begin() + 6 && ma0[5] == 77 && ma0[6] == 0;
|
||||
}
|
||||
|
||||
static_assert(test());
|
||||
|
||||
constexpr bool
|
||||
test_byte()
|
||||
{
|
||||
// PR libstdc++/94933
|
||||
std::array<char, 12> ma0{};
|
||||
|
||||
const auto outd = std::fill_n(ma0.begin(), 6, 77);
|
||||
|
||||
return outd == ma0.begin() + 6 && ma0[5] == 77 && ma0[6] == 0;
|
||||
}
|
||||
|
||||
static_assert( test_byte() );
|
||||
|
||||
struct S
|
||||
{
|
||||
int i = 0;
|
||||
};
|
||||
|
||||
constexpr bool
|
||||
test_nonscalar()
|
||||
{
|
||||
std::array<S, 12> ma0{};
|
||||
|
||||
const auto outd = std::fill_n(ma0.begin(), 6, S{77});
|
||||
|
||||
return outd == ma0.begin() + 6 && ma0[5].i == 77 && ma0[6].i == 0;
|
||||
}
|
||||
|
||||
static_assert( test_nonscalar() );
|
||||
|
|
Loading…
Reference in New Issue