mirror of
https://github.com/boostorg/container.git
synced 2026-01-19 04:02:17 +00:00
Implement C++26 heterogeneous operator[], refactor operator[] implementation.
This commit is contained in:
@@ -773,26 +773,43 @@ class flat_map
|
||||
//
|
||||
//////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! Effects: If there is no key equivalent to x in the flat_map, inserts
|
||||
//! value_type(x, T()) into the flat_map.
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || (defined(BOOST_CXX_VERSION) &&(BOOST_CXX_VERSION >= 201103L))
|
||||
//! Effects: If there is no key equivalent to k in the flat_map, inserts
|
||||
//! value_type(k, T()) into the flat_map.
|
||||
//!
|
||||
//! Returns: A reference to the mapped_type corresponding to x in *this.
|
||||
//! Returns: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
|
||||
mapped_type &operator[](const key_type& k);
|
||||
mapped_type &operator[](const key_type& k)
|
||||
{ return this->priv_subscript(k); }
|
||||
|
||||
//! Effects: If there is no key equivalent to x in the flat_map, inserts
|
||||
//! value_type(move(x), T()) into the flat_map (the key is move-constructed)
|
||||
//! Effects: If there is no key equivalent to k in the flat_map, inserts
|
||||
//! value_type(move(k), T()) into the flat_map (the key is move-constructed)
|
||||
//!
|
||||
//! Returns: A reference to the mapped_type corresponding to x in *this.
|
||||
//! Returns: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
|
||||
mapped_type &operator[](key_type &&k);
|
||||
#elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
|
||||
//in compilers like GCC 3.4, we can't catch temporaries
|
||||
inline mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
|
||||
inline mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
|
||||
mapped_type &operator[](key_type &&k)
|
||||
{ return this->priv_subscript(boost::move(k)); }
|
||||
|
||||
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(boost::forward<K>(k), T()) into the map
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic search time plus linear insertion time in case no equivalent key is present
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( mapped_type&
|
||||
, typename dtl::enable_if_transparent< key_compare
|
||||
BOOST_MOVE_I K
|
||||
BOOST_MOVE_I mapped_type&
|
||||
>::type) //transparent
|
||||
operator[](K &&k)
|
||||
{ return this->priv_subscript(boost::forward<K>(k)); }
|
||||
|
||||
#else
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
|
||||
#endif
|
||||
@@ -1807,29 +1824,26 @@ class flat_map
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
mapped_type &priv_subscript(const key_type& k)
|
||||
template<class K>
|
||||
inline mapped_type& priv_subscript(BOOST_FWD_REF(K) key)
|
||||
{
|
||||
const typename dtl::remove_cvref<K>::type & k = key; //Support emulated rvalue references
|
||||
iterator i = this->lower_bound(k);
|
||||
// i->first is greater than or equivalent to k.
|
||||
if (i == end() || key_comp()(k, (*i).first)){
|
||||
dtl::value_init<mapped_type> m;
|
||||
impl_value_type v(k, ::boost::move(m.m_t));
|
||||
i = dtl::force_copy<iterator>(this->m_flat_tree.insert_equal(::boost::move(v)));
|
||||
}
|
||||
return (*i).second;
|
||||
}
|
||||
mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
|
||||
{
|
||||
key_type &k = mk;
|
||||
iterator i = this->lower_bound(k);
|
||||
// i->first is greater than or equivalent to k.
|
||||
|
||||
if (i == end() || key_comp()(k, (*i).first)) {
|
||||
dtl::value_init<mapped_type> m;
|
||||
impl_value_type v(::boost::move(k), ::boost::move(m.m_t));
|
||||
i = dtl::force_copy<iterator>(this->m_flat_tree.insert_equal(::boost::move(v)));
|
||||
typename dtl::aligned_storage<sizeof(impl_value_type), dtl::alignment_of<impl_value_type>::value>::type v;
|
||||
impl_value_type *vp = move_detail::launder_cast<impl_value_type *>(&v);
|
||||
|
||||
impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator();
|
||||
boost::container::allocator_traits<impl_stored_allocator_type>::construct
|
||||
(r, vp, try_emplace_t(), ::boost::forward<K>(key));
|
||||
i = dtl::force_copy<iterator> (this->m_flat_tree.insert_equal
|
||||
(dtl::force_copy<impl_iterator>(i), ::boost::move(*vp)));
|
||||
vp->~impl_value_type();
|
||||
}
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
|
||||
@@ -555,26 +555,41 @@ class map
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || (defined(BOOST_CXX_VERSION) &&(BOOST_CXX_VERSION >= 201103L))
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(x, T()) into the map.
|
||||
//! value_type(k, T()) into the map.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
mapped_type& operator[](const key_type &k);
|
||||
mapped_type& operator[](const key_type& k)
|
||||
{ return this->priv_subscript(k); }
|
||||
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(boost::move(x), T()) into the map (the key is move-constructed)
|
||||
//! value_type(boost::move(k), T()) into the map (the key is move-constructed)
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
mapped_type& operator[](key_type &&k);
|
||||
#elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
|
||||
//in compilers like GCC 3.4, we can't catch temporaries
|
||||
inline mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
|
||||
inline mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
|
||||
mapped_type& operator[](key_type&& k)
|
||||
{ return this->priv_subscript(boost::move(k)); }
|
||||
|
||||
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(boost::forward<K>(k), T()) into the map
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to k in *this.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( mapped_type&
|
||||
, typename dtl::enable_if_transparent<key_compare BOOST_MOVE_I K BOOST_MOVE_I mapped_type&>::type
|
||||
)
|
||||
operator[](K&& k)
|
||||
{ return this->priv_subscript(boost::forward<K>(k)); }
|
||||
|
||||
#else
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
|
||||
#endif
|
||||
@@ -948,7 +963,7 @@ class map
|
||||
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(forward<K>(k)),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only if the
|
||||
|
||||
@@ -1697,6 +1697,30 @@ bool test_heterogeneous_insert()
|
||||
return false;
|
||||
if (cmap1.find(2)->second != 'c')
|
||||
return false;
|
||||
|
||||
//operator[]
|
||||
typename map_t::mapped_type const *pm = &map1.find(2)->second;
|
||||
typename map_t::mapped_type &m = map1[2];
|
||||
if(m != 'c')
|
||||
return false;
|
||||
if(&m != pm)
|
||||
return false;
|
||||
|
||||
map1[2] = 'd';
|
||||
if (cmap1.find(2)->second != 'd')
|
||||
return false;
|
||||
if(&m != &map1[2])
|
||||
return false;
|
||||
|
||||
map1[3] = 'e';
|
||||
if (cmap1.find(3)->second != 'e')
|
||||
return false;
|
||||
if(map1[3] != map1[3])
|
||||
return false;
|
||||
|
||||
if (map1[4] != 0)
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user