[libcxx-commits] [libcxx] [libc++] Added segmented iterator for std::fill (PR #104680)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 16 04:00:07 PDT 2024


================
@@ -21,23 +24,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 // fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
 
-template <class _ForwardIterator, class _Tp>
+template < class _ForwardIterator,
+           class _Tp,
+           __enable_if_t<!__has_random_access_iterator_category<_ForwardIterator>::value, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag) {
+__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
   for (; __first != __last; ++__first)
     *__first = __value;
 }
 
-template <class _RandomAccessIterator, class _Tp>
+template <class _RandomAccessIterator,
+          class _Tp,
+          __enable_if_t<__has_random_access_iterator_category<_RandomAccessIterator>::value &&
+                            !__is_segmented_iterator<_RandomAccessIterator>::value,
+                        int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag) {
+__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value) {
   std::fill_n(__first, __last - __first, __value);
 }
 
+template <class _SegmentedIterator,
+          class _Tp,
+          __enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+__fill(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value) {
+  std::for_each(__first, __last, [__value](_Tp& __val) { __val = __value; });
----------------
NoumanAmir657 wrote:

@philnik777 

I tried the latter case as mentioned above but it leads to this test failing `count.pass.cpp` and `ranges.count.pass.cpp`.
```
# | In file included from /home/nouman-10x/con_llvm_project/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp:19:
# | In file included from /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/algorithm:1835:
# | In file included from /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:12:
# | In file included from /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill_n.h:12:
# | /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/for_each.h:34:5: error: no matching function for call to object of type '(lambda at /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:58:34)'
# |    34 |     __f(*__first);
# |       |     ^~~
# | /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:58:8: note: in instantiation of function template specialization 'std::for_each<std::__bit_iterator<std::vector<bool>, false>, (lambda at /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:58:34)>' requested here
# |    58 |   std::for_each(__first, __last, [__value](_Tp& __val) { __val = __value; });
# |       |        ^
# | /home/nouman-10x/con_llvm_project/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp:45:14: note: in instantiation of function template specialization 'std::fill<std::__bit_iterator<std::vector<bool>, false>, bool>' requested here
# |    45 |         std::fill(vec.begin(), vec.end(), false);
# |       |              ^
# | /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:58:34: note: candidate function not viable: no known conversion from 'reference' (aka 'std::__bit_reference<std::vector<bool>>') to 'bool &' for 1st argument
# |    58 |   std::for_each(__first, __last, [__value](_Tp& __val) { __val = __value; });
# |       |                                  ^         ~~~~~~~~~~
# | /home/nouman-10x/con_llvm_project/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp:59:17: error: static assertion expression is not an integral constant expression
# |    59 |   static_assert(test());
# |       |                 ^~~~~~
# | /home/nouman-10x/con_llvm_project/build/libcxx/test-suite-install/include/c++/v1/__algorithm/fill.h:58:3: note: subexpression not valid in a constant expression
# |    58 |   std::for_each(__first, __last, [__value](_Tp& __val) { __val = __value; });
# |       |   ^
# | /home/nouman-10x/con_llvm_project/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp:45:9: note: in call to 'fill<std::__bit_iterator<std::vector<bool>, false>, bool>({&{*new unsigned long[5]#0}[0], 0}, {&{*new unsigned long[5]#0}[5], 0}, false)'
# |    45 |         std::fill(vec.begin(), vec.end(), false);
# |       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | /home/nouman-10x/con_llvm_project/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp:59:17: note: in call to 'test()'
# |    59 |   static_assert(test());
# |       |                 ^~~~~~
# | 2 errors generated.
# `-----------------------------
# error: command failed with exit status: 1
```
It seems like this is occurring because bool vectors are treated differently.

https://github.com/llvm/llvm-project/pull/104680


More information about the libcxx-commits mailing list