[libcxx-commits] [PATCH] D107932: [libc++] Do not require movability in __non_propagating_cache::__emplace_deref

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 11 14:54:43 PDT 2021


Quuxplusone added inline comments.


================
Comment at: libcxx/include/__ranges/non_propagating_cache.h:46-49
+      template<class ..._Args>
+      constexpr explicit __wrapper(_Args&& ...__args) : __t_(_VSTD::forward<_Args>(__args)...) { }
+      template<class _Iter>
+      constexpr explicit __wrapper(__deref_tag, _Iter const& __iter) : __t_(*__iter) { }
----------------
This overload set has the distinct smell of "greedy perfect-forwarding overload eats things you wouldn't expect." You use it below like this:
```
    constexpr _Tp& __emplace_deref(_Iter const& __iter) {
      return __value_.emplace(__deref_tag{}, __iter).__t_;
    }
```
which I think is fine; but if you (or future-you) changes it to
```
    constexpr _Tp& __emplace_deref(_Iter __iter) {
      return __value_.emplace(__deref_tag{}, __iter).__t_;
    }
```
then suddenly it'll pick the wrong overload. Right?
I'm not 100% sure this is worth fixing, but if it is, then I think I'd fix it by adding a second tag type, say `struct __no_deref_tag { }`, and making the constructor on line 47 take `__wrapper(__no_deref_tag, _Args&&...)`.


================
Comment at: libcxx/include/__ranges/non_propagating_cache.h:85-88
     _LIBCPP_HIDE_FROM_ABI
-    constexpr _Tp& operator*() { return *__value_; }
+    constexpr _Tp& operator*() { return __value_->__t_; }
     _LIBCPP_HIDE_FROM_ABI
+    constexpr _Tp const& operator*() const { return __value_->__t_; }
----------------
Any appetite for making these named members (e.g. `npc.__value()`)?
Besides my usual advice that operators can be harder to read and/or go-to-definition of, it also just occurred to me that operators are subject to ADL but member functions are not:
https://godbolt.org/z/EsasGzoad
(I don't think the Standard cares about ADL in this instance; but any time I see a chance to ADL-proof something... ;))


================
Comment at: libcxx/test/libcxx/ranges/range.nonprop.cache/emplace.pass.cpp:25
+  template<int J>
+  constexpr friend bool operator==(X const& a, X<J> const& b) { return I == J && a.value == b.value; }
+};
----------------
`friend constexpr` https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling-knife/
and consider line-breaking somewhere.

High-level comment: I'm not sure what benefit you get from the templated `operator==` or the use of `tuple`. If you just want something with a couple of weird constructors, why not `string`?
```
using Cache = std::ranges::__non_propagating_cache<std::string>;
Cache cache;
std::string& result = cache.__emplace();
assert(&result == &cache.__value() && result == "");

Cache cache;
std::string& result = cache.__emplace("foobar");
assert(&result == &cache.__value() && result == "foobar");

Cache cache;
std::string& result = cache.__emplace("foobar", 3);
assert(&result == &cache.__value() && result == "foo");
```
In this PR, though, it seems more important to test that it's legal to `__emplace` a `NonMovable`, similar to what you did below in the `__emplace_deref` test.


================
Comment at: libcxx/test/libcxx/ranges/range.nonprop.cache/emplace_deref.pass.cpp:74-82
+  // Make sure that we do not require the type to be movable when we emplace-deref it.
+  // Copy elision should be performed instead, see http://eel.is/c++draft/range.nonprop.cache#note-1.
+  {
+    using Cache = std::ranges::__non_propagating_cache<NonMovable>;
+    Cache cache;
+    NonMovable& result = cache.__emplace_deref(on_the_fly_iterator_to<NonMovable>{3});
+    assert(&result == &*cache);
----------------
(This test LGTM.)


================
Comment at: libcxx/test/libcxx/ranges/range.nonprop.cache/has_value.pass.cpp:32
   {
-    Cache cache; cache.__set(T{});
+    Cache cache; cache.__emplace(T{});
     assert(cache.__has_value());
----------------
I believe you could delete the characters `T{}` here, if you wanted.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D107932



More information about the libcxx-commits mailing list