[libcxx-commits] [PATCH] D142335: [libc++][ranges] Implement `ranges::to`.

Konstantin Varlamov via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu May 4 01:54:06 PDT 2023


var-const marked 13 inline comments as done.
var-const added inline comments.


================
Comment at: libcxx/include/__ranges/to.h:47
+
+// Note: in the Standard, `reservable-container` is a `constexpr bool` variable. However, GCC has a compiler bug that
+// makes short-circuiting not work properly in that case, so use a concept as a workaround.
----------------
philnik wrote:
> Do you know whether GCC 13 fixes that bug? If yes, maybe make this a TODO, since we will switch very soon?
Hmm, this was a while ago, but looking up my notes, it looks like I was conflating two issues here. The compiler with a bug in this case was Clang 15: https://godbolt.org/z/aGrE1oP1v. I'll switch back to using a `constexpr bool` variable for consistency with the Standard and see if anything breaks on the CI. Thanks for calling the attention to this!


================
Comment at: libcxx/include/deque:1823
+deque<_Tp, _Allocator>::__insert_bidirectional(const_iterator __p, _BiIter __f, _Sentinel __sent, size_type __n) {
+    auto __l = std::ranges::next(__f, __sent);
     size_type __pos = __p - begin();
----------------
ldionne wrote:
> This does have the same problem that we're re-walking the whole input sequence again in some cases, let's see if there's a solution for that.
Hmm, how about using two overloads, one where the type of `__l` is an exact match for `_BiIter` and one when it's a different sentinel type? That way, we can only call `next` when the types differ (and thus `next` cannot be reduced to simply return `__sent`).


================
Comment at: libcxx/include/vector:1478-1479
         {
-            __growing = true;
-            __mid =  __first;
-            std::advance(__mid, size());
+            std::advance(__first, size());
+            __construct_at_end(__first, __last, __new_size - size());
+
----------------
ldionne wrote:
> var-const wrote:
> > ldionne wrote:
> > > This doesn't seem to work, I think we're consuming the first `size()` elements from `__first` and then copying the rest into the vector only. I think this also means there's a gap in the testing.
> > Thanks! I think this is the right form:
> > ```
> > if (__new_size <= capacity()) {
> >   if (__new_size > size()) {
> >     _ForwardIterator __mid = __first;
> >     std::advance(__mid, size());
> > 
> >     std::copy(__first, __mid, this->__begin_);
> >     __construct_at_end(__mid, __last, __new_size - size());
> > 
> >   } else {
> >     pointer __m = std::copy(__first, __last, this->__begin_);
> >     this->__destruct_at_end(__m);
> >   }
> > }
> > ```
> > I think it's actually more readable without the `__growing` variable.
> ```
> if (__new_size <= capacity()) {
>   if (__new_size > size()) {
>     _ForwardIterator __mid = std::next(__first, size());
> 
>     std::copy(__first, __mid, this->__begin_);
>     __construct_at_end(__mid, __last, __new_size - size());
> 
>   } else {
>     pointer __m = std::copy(__first, __last, this->__begin_);
>     this->__destruct_at_end(__m);
>   }
> }
> ```
> 
> Yeah, I think that works!
Note: still need to fix the testing part.


================
Comment at: libcxx/include/vector:1921
 {
-    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this,
-                         "vector::insert(iterator, range) called with an iterator not referring to this vector");
+  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this,
+                        "vector::insert(iterator, range) called with an iterator not referring to this vector");
----------------
ldionne wrote:
> This should be in `__insert_with_sentinel`, I think.
I think I originally left it there due to the way the error message is written (referring to the exact name of the invoking function). But I don't think we lose much by making it slightly more generic, not to mention that the debug mode is effectively non-operational anyway.


================
Comment at: libcxx/test/std/containers/insert_range_helpers.h:31
+
+// A simple literal-type container. It can be used as a `constexpr` global variable (which isn't supported by
+// `std::vector`).
----------------
ldionne wrote:
> I think you don't need this class if you don't store your test cases in global variables. Then you could simply use `std::string` and it would work in `constexpr` too. IMO that would be better since this class is very specific.
I tried changing this but not sure it's worth it. `constexpr` variables have a very nice property that if one of them is accidentally unused (i.e. a test case is omitted), the compiler produces an error. The class is pretty small and I don't think it adds that much maintenance burden. I remember implementing something similar before to work around some other limitations of `vector` and `string` which makes me suspect that having full control over the class's implementation has some value.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142335/new/

https://reviews.llvm.org/D142335



More information about the libcxx-commits mailing list