@@ -773,26 +773,43 @@ class flat_map
773773 //
774774 // ////////////////////////////////////////////
775775
776- #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
777- // ! Effects: If there is no key equivalent to x in the flat_map, inserts
778- // ! value_type(x , T()) into the flat_map.
776+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || (defined(BOOST_CXX_VERSION) &&(BOOST_CXX_VERSION >= 201103L))
777+ // ! Effects: If there is no key equivalent to k in the flat_map, inserts
778+ // ! value_type(k , T()) into the flat_map.
779779 // !
780- // ! Returns: A reference to the mapped_type corresponding to x in *this.
780+ // ! Returns: A reference to the mapped_type corresponding to k in *this.
781781 // !
782782 // ! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
783- mapped_type &operator [](const key_type& k);
783+ mapped_type &operator [](const key_type& k)
784+ { return this ->priv_subscript (k); }
784785
785- // ! Effects: If there is no key equivalent to x in the flat_map, inserts
786- // ! value_type(move(x ), T()) into the flat_map (the key is move-constructed)
786+ // ! Effects: If there is no key equivalent to k in the flat_map, inserts
787+ // ! value_type(move(k ), T()) into the flat_map (the key is move-constructed)
787788 // !
788- // ! Returns: A reference to the mapped_type corresponding to x in *this.
789+ // ! Returns: A reference to the mapped_type corresponding to k in *this.
789790 // !
790791 // ! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
791- mapped_type &operator [](key_type &&k);
792- #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
793- // in compilers like GCC 3.4, we can't catch temporaries
794- inline mapped_type& operator [](const key_type &k) { return this ->priv_subscript (k); }
795- inline mapped_type& operator [](BOOST_RV_REF(key_type) k) { return this ->priv_subscript (::boost::move (k)); }
792+ mapped_type &operator [](key_type &&k)
793+ { return this ->priv_subscript (boost::move (k)); }
794+
795+ // ! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
796+ // !
797+ // ! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
798+ // ! value_type(boost::forward<K>(k), T()) into the map
799+ // !
800+ // ! <b>Returns</b>: A reference to the mapped_type corresponding to k in *this.
801+ // !
802+ // ! <b>Complexity</b>: Logarithmic search time plus linear insertion time in case no equivalent key is present
803+ template <class K >
804+ inline BOOST_CONTAINER_DOC1ST
805+ ( mapped_type&
806+ , typename dtl::enable_if_transparent< key_compare
807+ BOOST_MOVE_I K
808+ BOOST_MOVE_I mapped_type&
809+ >::type) // transparent
810+ operator [](K &&k)
811+ { return this ->priv_subscript (boost::forward<K>(k)); }
812+
796813 #else
797814 BOOST_MOVE_CONVERSION_AWARE_CATCH ( operator [] , key_type, mapped_type&, this ->priv_subscript)
798815 #endif
@@ -1807,29 +1824,26 @@ class flat_map
18071824
18081825 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
18091826 private:
1810- mapped_type &priv_subscript (const key_type& k)
1811- {
1812- iterator i = this ->lower_bound (k);
1813- // i->first is greater than or equivalent to k.
1814- if (i == end () || key_comp ()(k, (*i).first )){
1815- dtl::value_init<mapped_type> m;
1816- impl_value_type v (k, ::boost::move (m.m_t ));
1817- i = dtl::force_copy<iterator>(this ->m_flat_tree .insert_equal (::boost::move (v)));
1818- }
1819- return (*i).second ;
1820- }
1821- mapped_type &priv_subscript (BOOST_RV_REF(key_type) mk)
1827+ template <class K >
1828+ inline mapped_type& priv_subscript (BOOST_FWD_REF(K) key)
18221829 {
1823- key_type & k = mk;
1830+ const typename dtl::remove_cvref<K>::type & k = key; // Support emulated rvalue references
18241831 iterator i = this ->lower_bound (k);
1825- // i->first is greater than or equivalent to k.
1832+
18261833 if (i == end () || key_comp ()(k, (*i).first )) {
1827- dtl::value_init<mapped_type> m;
1828- impl_value_type v (::boost::move (k), ::boost::move (m.m_t ));
1829- i = dtl::force_copy<iterator>(this ->m_flat_tree .insert_equal (::boost::move (v)));
1834+ typename dtl::aligned_storage<sizeof (impl_value_type), dtl::alignment_of<impl_value_type>::value>::type v;
1835+ impl_value_type *vp = move_detail::launder_cast<impl_value_type *>(&v);
1836+
1837+ impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator ();
1838+ boost::container::allocator_traits<impl_stored_allocator_type>::construct
1839+ (r, vp, try_emplace_t (), ::boost::forward<K>(key));
1840+ i = dtl::force_copy<iterator> (this ->m_flat_tree .insert_equal
1841+ (dtl::force_copy<impl_iterator>(i), ::boost::move (*vp)));
1842+ vp->~impl_value_type ();
18301843 }
18311844 return (*i).second ;
18321845 }
1846+
18331847 #endif // #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
18341848};
18351849
0 commit comments