erik.pilkington added inline comments.
================ Comment at: libcxx/include/__hash_table:2165 +#if _LIBCPP_STD_VER > 14 +template <class _Tp, class _Hash, class _Equal, class _Alloc> +template <class _NodeHandle, class _InsertReturnType> ---------------- ldionne wrote: > When a function is declared with a visibility macro > (`_LIBCPP_INLINE_VISIBILITY` in this case), I think it is customary in libc++ > to repeat the visibility macro on the definition as well. If that's correct, > apply here and to other similar functions below, and also in `__tree`. I can't say I know libc++'s policy here either, but it couldn't hurt, so I added the attributes to the new patch. Maybe @EricWF or @mclow.lists could weigh in here? ================ Comment at: libcxx/include/__hash_table:2212 + allocator_type __alloc(__node_alloc()); + return _NodeHandle(remove(__p).release(), __alloc); +} ---------------- ldionne wrote: > Just a quick Q: am I mistaken or `remove()` is not part of the > `unordered_map` API? We're not naming it `__remove()` just because we already > have other functions called `remove()`, so any macro redefining `remove` > would already break things -- is that the idea? Yep, I think that was the thinking. IMO it would be nice to just call it `__remove` to avoid any confusion. ================ Comment at: libcxx/include/__node_handle:36 +template <class _NodeType, class _Alloc> +class __node_handle_base +{ ---------------- ldionne wrote: > I'd like to suggest a different approach for implementing the node handles > for sets and maps. I believe this would simplify things slightly: > > ``` > template <class _NodeType, class _Alloc, template <class...> class > _MapOrSetSpecifics> > class __basic_node_handle > : public _MapOrSetSpecifics<_NodeType, __basic_node_handle<_NodeType, > _Alloc, _MapOrSetSpecifics>> > { > // same as right now > }; > ``` > > Then, you can get the two different node handles by simply providing the > methods in the base class: > > ``` > template <class _NodeType, class _Derived> > struct __map_node_handle_specifics { > using key_type = typename _NodeType::__node_value_type::key_type; > using mapped_type = typename _NodeType::__node_value_type::mapped_type; > > _LIBCPP_INLINE_VISIBILITY > key_type& key() const > { > return static_cast<_Derived > const*>(this)->__ptr_->__value_.__ref().first; > } > > _LIBCPP_INLINE_VISIBILITY > mapped_type& mapped() const > { > return static_cast<_Derived > const*>(this)->__ptr_->__value_.__ref().second; > } > }; > > template <class _NodeType, class _Derived> > struct __set_node_handle_specifics { > using value_type = typename _NodeType::__node_value_type; > > _LIBCPP_INLINE_VISIBILITY > value_type& value() const > { > return static_cast<_Derived const*>(this)->__ptr_->__value_; > } > }; > > template <class _NodeType, class _Alloc> > using __map_node_handle = __basic_node_handle<_NodeType, _Alloc, > __map_node_handle_specifics>; > > template <class _NodeType, class _Alloc> > using __set_node_handle = __basic_node_handle<_NodeType, _Alloc, > __set_node_handle_specifics>; > ``` > > This is a classic application of the CRTP. I believe it would reduce the > amount of boilerplate currently required for special member functions. It's > possible that you thought of this and realized it didn't work for a reason > I'm missing right now, too, but the idea seems to work on the surface: > https://wandbox.org/permlink/nMaKEg43PVJpA0ld. > > You don't have to do this, but please consider it if you think it would > simplify the code. > Oh, neat! That's a great idea, I didn't even consider CRTP here for some reason. Makes this simpler though. I added this to the new patch. ================ Comment at: libcxx/include/map:915 + + __base& __get_tree() { return __tree_; } + ---------------- ldionne wrote: > I believe this function should be marked with `_LIBCPP_INLINE_VISIBILITY` -- > even though in practice the compiler will probably always inline it. > > Also, you don't seem to be using that function at all in the diff -- is that > right? > > So please either mark with `_LIBCPP_INLINE_VISIBILITY` and use it, or remove > it altogether. This comment applies to all 8 containers to which similar > methods were added. Oh, sorry! This was used in the implementation of `merge`, which I moved to a follow-up. I'll sink it down there and add the visibility attribute. ================ Comment at: libcxx/include/set:399 +template <class _Key, class _Compare, class _Allocator> +class multiset; ---------------- ldionne wrote: > Is this forward declaration necessary? No, nice catch! This was also supposed to be a part of the follow-up, I'll move it there. ================ Comment at: libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_extract.pass.cpp:14 + +// class unordered_map + ---------------- ldionne wrote: > Please be more specific about which functions you're testing. I find it > useful to look at those comments to quickly see what exact signatures are > being tested when I'm looking for tests that exercice some specific piece of > code. > > Actually, perhaps you should extract those tests into multiple files: > `unord.map/unord.map.modifiers/insert.node_handle.pass.cpp` => test overload > of `insert` on `node_type` > `unord.map/unord.map.modifiers/insert.hint_node_handle.pass.cpp` => test > overload of `insert` with a hint and a `node_type` > `unord.map/unord.map.modifiers/extract.node_handle.pass.cpp` => test overload > of `extract` on `node_type` > `unord.map/unord.map.modifiers/extract.iterator.pass.cpp` => test overload of > `extract` on iterator > `unord.map/insert_return_type.pass.cpp` => test `insert_return_type` > `unord.map/node_type.pass.cpp` => test node handle operations > > I believe this would be more consistent with the way things are currently > organized for other functions. This comment applies to all containers touched > by this review. Okay, the new patch divides up the tests for each container into 4 files: `extract_iterator.pass.cpp`, `extract_key.pass.cpp`, `insert_node_type.pass.cpp`, and `insert_node_type_hint.pass.cpp`. I decided to move the insert_return_type and node_type testing to `container.node/node_handle.pass.cpp` because they don't really depend on any specific container, and it matches how the standard defines these. ================ Comment at: libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_extract.pass.cpp:23 +{ +typedef std::unordered_map<int, int> int_map_type; +using intIRT = int_map_type::insert_return_type; ---------------- ldionne wrote: > Consider using `using XXX = YYY` consistently. done! ================ Comment at: libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_extract.pass.cpp:33 + std::equal_to<Counter<int> >, + min_allocator<std::pair<const Counter<int>, Counter<int> > > > + map_type; ---------------- ldionne wrote: > You don't need spaces between consecutive `>`'s since those tests are not > supported in C++03. Feel free to keep them or remove them, I'm just pointing > it out. Sure, sorry! clang-format adds these in because it isn't smart enough to know when we're in a C++11 context. ================ Comment at: libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_extract.pass.cpp:99-101 + the_map::iterator i = s.begin(); + std::advance(i, 2); + assert(i == s.end()); ---------------- ldionne wrote: > Why is this test useful? I guess it isn't really, it was more of a sanity check. https://reviews.llvm.org/D46845 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits