Skip to content

Commit 7a2192b

Browse files
committed
Fixes #323 ("flat_tree::try_emplace UB")
1 parent ee24095 commit 7a2192b

File tree

5 files changed

+122
-43
lines changed

5 files changed

+122
-43
lines changed

doc/container.qbk

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,9 @@ use [*Boost.Container]? There are several reasons for that:
14361436

14371437
[section:release_notes_boost_1_91_00 Boost 1.91 Release]
14381438

1439-
* Implemented heterogeneous overloads from C++03 ([@http://wg21.link/p2077r3 P2077]) and C++26 ([@http://wg21.link/P2363 P2363]).
1439+
* Implemented heterogeneous overloads from C++23 ([@http://wg21.link/p2077r3 P2077]) and C++26 ([@http://wg21.link/P2363 P2363]).
1440+
* Fixed bugs/issues:
1441+
* [@https://github.com/boostorg/container/issues/323 GitHub #323: ['"flat_tree::try_emplace UB"]].
14401442

14411443
[endsect]
14421444

include/boost/container/detail/flat_tree.hpp

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,16 +1067,32 @@ class flat_tree
10671067
return this->insert_equal(hint, ::boost::move(*pval));
10681068
}
10691069

1070+
template <class KeyType, class... Args>
1071+
inline std::pair<iterator, bool> try_emplace
1072+
(BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
1073+
{
1074+
std::pair<iterator,bool> ret;
1075+
insert_commit_data data;
1076+
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1077+
ret.second = this->priv_insert_unique_prepare(k, data);
1078+
1079+
if(!ret.second){
1080+
ret.first = this->nth(size_type(data.position - this->cbegin()));
1081+
}
1082+
else{
1083+
ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
1084+
}
1085+
return ret;
1086+
}
1087+
10701088
template <class KeyType, class... Args>
10711089
inline std::pair<iterator, bool> try_emplace
10721090
(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
10731091
{
10741092
std::pair<iterator,bool> ret;
10751093
insert_commit_data data;
10761094
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1077-
ret.second = hint == const_iterator()
1078-
? this->priv_insert_unique_prepare(k, data)
1079-
: this->priv_insert_unique_prepare(hint, k, data);
1095+
ret.second = this->priv_insert_unique_prepare(hint, k, data);
10801096

10811097
if(!ret.second){
10821098
ret.first = this->nth(size_type(data.position - this->cbegin()));
@@ -1134,15 +1150,30 @@ class flat_tree
11341150
return this->insert_equal(hint, ::boost::move(*pval));\
11351151
}\
11361152
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
1153+
inline std::pair<iterator, bool>\
1154+
try_emplace(BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1155+
{\
1156+
std::pair<iterator,bool> ret;\
1157+
insert_commit_data data;\
1158+
const typename remove_cvref<KeyType>::type & k = key;\
1159+
ret.second = this->priv_insert_unique_prepare(k, data);\
1160+
\
1161+
if(!ret.second){\
1162+
ret.first = this->nth(size_type(data.position - this->cbegin()));\
1163+
}\
1164+
else{\
1165+
ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1166+
}\
1167+
return ret;\
1168+
}\
1169+
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
11371170
inline std::pair<iterator, bool>\
11381171
try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
11391172
{\
11401173
std::pair<iterator,bool> ret;\
11411174
insert_commit_data data;\
11421175
const typename remove_cvref<KeyType>::type & k = key;\
1143-
ret.second = hint == const_iterator()\
1144-
? this->priv_insert_unique_prepare(k, data)\
1145-
: this->priv_insert_unique_prepare(hint, k, data);\
1176+
ret.second = this->priv_insert_unique_prepare(hint, k, data);\
11461177
\
11471178
if(!ret.second){\
11481179
ret.first = this->nth(size_type(data.position - this->cbegin()));\
@@ -1158,15 +1189,30 @@ class flat_tree
11581189

11591190
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
11601191

1192+
template<class KeyType, class M>
1193+
std::pair<iterator, bool> insert_or_assign(BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
1194+
{
1195+
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1196+
std::pair<iterator,bool> ret;
1197+
insert_commit_data data;
1198+
ret.second = this->priv_insert_unique_prepare(k, data);
1199+
if(!ret.second){
1200+
ret.first = this->nth(size_type(data.position - this->cbegin()));
1201+
ret.first->second = boost::forward<M>(obj);
1202+
}
1203+
else{
1204+
ret.first = this->m_data.m_seq.emplace(data.position, boost::forward<KeyType>(key), boost::forward<M>(obj));
1205+
}
1206+
return ret;
1207+
}
1208+
11611209
template<class KeyType, class M>
11621210
std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
11631211
{
11641212
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
11651213
std::pair<iterator,bool> ret;
11661214
insert_commit_data data;
1167-
ret.second = hint == const_iterator()
1168-
? this->priv_insert_unique_prepare(k, data)
1169-
: this->priv_insert_unique_prepare(hint, k, data);
1215+
ret.second = this->priv_insert_unique_prepare(hint, k, data);
11701216
if(!ret.second){
11711217
ret.first = this->nth(size_type(data.position - this->cbegin()));
11721218
ret.first->second = boost::forward<M>(obj);

include/boost/container/detail/tree.hpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,15 +1005,27 @@ class tree
10051005
return ret;
10061006
}
10071007

1008+
template <class KeyType, class... Args>
1009+
inline std::pair<iterator, bool> try_emplace
1010+
(BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
1011+
{
1012+
insert_commit_data data;
1013+
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1014+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data);
1015+
if(ret.second){
1016+
ret.first = this->icont().insert_unique_commit
1017+
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
1018+
}
1019+
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
1020+
}
1021+
10081022
template <class KeyType, class... Args>
10091023
inline std::pair<iterator, bool> try_emplace
10101024
(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
10111025
{
10121026
insert_commit_data data;
10131027
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1014-
std::pair<iiterator, bool> ret =
1015-
hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)
1016-
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
1028+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
10171029
if(ret.second){
10181030
ret.first = this->icont().insert_unique_commit
10191031
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
@@ -1054,14 +1066,26 @@ class tree
10541066
}\
10551067
\
10561068
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
1069+
inline std::pair<iterator, bool>\
1070+
try_emplace(BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1071+
{\
1072+
insert_commit_data data;\
1073+
const typename remove_cvref<KeyType>::type & k = key;\
1074+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data);\
1075+
if(ret.second){\
1076+
ret.first = this->icont().insert_unique_commit\
1077+
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
1078+
}\
1079+
return std::pair<iterator, bool>(iterator(ret.first), ret.second);\
1080+
}\
1081+
\
1082+
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
10571083
inline std::pair<iterator, bool>\
10581084
try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
10591085
{\
10601086
insert_commit_data data;\
10611087
const typename remove_cvref<KeyType>::type & k = key;\
1062-
std::pair<iiterator, bool> ret =\
1063-
hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)\
1064-
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\
1088+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\
10651089
if(ret.second){\
10661090
ret.first = this->icont().insert_unique_commit\
10671091
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
@@ -1114,14 +1138,27 @@ class tree
11141138
this->insert_equal_convertible(*first);
11151139
}
11161140

1141+
template<class KeyType, class M>
1142+
std::pair<iterator, bool> insert_or_assign(BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
1143+
{
1144+
insert_commit_data data;
1145+
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1146+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data);
1147+
if(ret.second){
1148+
ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
1149+
}
1150+
else{
1151+
ret.first->get_data().second = boost::forward<M>(obj);
1152+
}
1153+
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
1154+
}
1155+
11171156
template<class KeyType, class M>
11181157
std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
11191158
{
11201159
insert_commit_data data;
11211160
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
1122-
std::pair<iiterator, bool> ret =
1123-
hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data)
1124-
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
1161+
std::pair<iiterator, bool> ret = this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
11251162
if(ret.second){
11261163
ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
11271164
}

include/boost/container/flat_map.hpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -826,9 +826,7 @@ class flat_map
826826
inline std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
827827
{
828828
return dtl::force_copy< std::pair<iterator, bool> >
829-
(this->m_flat_tree.insert_or_assign
830-
( impl_const_iterator(), k, ::boost::forward<M>(obj))
831-
);
829+
(this->m_flat_tree.insert_or_assign(k, ::boost::forward<M>(obj)));
832830
}
833831

834832
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
@@ -843,9 +841,7 @@ class flat_map
843841
inline std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
844842
{
845843
return dtl::force_copy< std::pair<iterator, bool> >
846-
(this->m_flat_tree.insert_or_assign
847-
( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
848-
);
844+
(this->m_flat_tree.insert_or_assign(::boost::move(k), ::boost::forward<M>(obj)));
849845
}
850846

851847
//! <b>Requires</b>: This overload is available only if key_compare::is_transparent exists.
@@ -870,9 +866,7 @@ class flat_map
870866
insert_or_assign(BOOST_FWD_REF(K) k, BOOST_FWD_REF(M) obj)
871867
{
872868
return dtl::force_copy< std::pair<iterator, bool> >
873-
(this->m_flat_tree.insert_or_assign
874-
( impl_const_iterator(), ::boost::forward<K>(k), ::boost::forward<M>(obj))
875-
);
869+
(this->m_flat_tree.insert_or_assign(::boost::forward<K>(k), ::boost::forward<M>(obj)));
876870
}
877871

878872
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
@@ -1095,7 +1089,7 @@ class flat_map
10951089
inline std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
10961090
{
10971091
return dtl::force_copy< std::pair<iterator, bool> >(
1098-
m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
1092+
m_flat_tree.try_emplace(k, boost::forward<Args>(args)...));
10991093
}
11001094

11011095
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
@@ -1131,7 +1125,7 @@ class flat_map
11311125
inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
11321126
{
11331127
return dtl::force_copy< std::pair<iterator, bool> >
1134-
(m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
1128+
(m_flat_tree.try_emplace(boost::move(k), boost::forward<Args>(args)...));
11351129
}
11361130

11371131
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
@@ -1178,7 +1172,7 @@ class flat_map
11781172
try_emplace(BOOST_FWD_REF(K) k, BOOST_FWD_REF(Args)... args)
11791173
{
11801174
return dtl::force_copy< std::pair<iterator, bool> >
1181-
(m_flat_tree.try_emplace(impl_const_iterator(), boost::forward<K>(k), boost::forward<Args>(args)...));
1175+
(m_flat_tree.try_emplace(boost::forward<K>(k), boost::forward<Args>(args)...));
11821176
}
11831177

11841178
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
@@ -1228,7 +1222,7 @@ class flat_map
12281222
inline std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
12291223
{\
12301224
return dtl::force_copy< std::pair<iterator, bool> >\
1231-
(m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1225+
(m_flat_tree.try_emplace(k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
12321226
}\
12331227
\
12341228
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
@@ -1240,7 +1234,7 @@ class flat_map
12401234
inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
12411235
{\
12421236
return dtl::force_copy< std::pair<iterator, bool> >\
1243-
(m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1237+
(m_flat_tree.try_emplace(boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
12441238
}\
12451239
\
12461240
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
@@ -1258,7 +1252,7 @@ class flat_map
12581252
try_emplace(BOOST_FWD_REF(K) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
12591253
{ \
12601254
return dtl::force_copy< std::pair<iterator BOOST_MOVE_I bool> > \
1261-
(m_flat_tree.try_emplace(impl_const_iterator() BOOST_MOVE_I boost::forward<K>(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N)); \
1255+
(m_flat_tree.try_emplace(boost::forward<K>(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N)); \
12621256
} \
12631257
\
12641258
template <class K BOOST_MOVE_I##N BOOST_MOVE_CLASS##N> \

include/boost/container/map.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ class map
608608
//! <b>Complexity</b>: Logarithmic in the size of the container.
609609
template <class M>
610610
inline std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
611-
{ return this->base_t::insert_or_assign(const_iterator(), k, ::boost::forward<M>(obj)); }
611+
{ return this->base_t::insert_or_assign(k, ::boost::forward<M>(obj)); }
612612

613613
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
614614
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
@@ -624,7 +624,7 @@ class map
624624
//! <b>Complexity</b>: Logarithmic in the size of the container.
625625
template <class M>
626626
inline std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
627-
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::move(k), ::boost::forward<M>(obj)); }
627+
{ return this->base_t::insert_or_assign(::boost::move(k), ::boost::forward<M>(obj)); }
628628

629629
//! <b>Requires</b>: This overload is available only if key_compare::is_transparent exists.
630630
//!
@@ -649,7 +649,7 @@ class map
649649
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool>
650650
>::type) //transparent
651651
insert_or_assign(BOOST_FWD_REF(K) k, BOOST_FWD_REF(M) obj)
652-
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::forward<K>(k), ::boost::forward<M>(obj)); }
652+
{ return this->base_t::insert_or_assign(::boost::forward<K>(k), ::boost::forward<M>(obj)); }
653653

654654
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
655655
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
@@ -958,7 +958,7 @@ class map
958958
//! <b>Complexity</b>: Logarithmic.
959959
template <class... Args>
960960
inline std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
961-
{ return this->base_t::try_emplace(const_iterator(), k, boost::forward<Args>(args)...); }
961+
{ return this->base_t::try_emplace(k, boost::forward<Args>(args)...); }
962962

963963
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
964964
//! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
@@ -988,7 +988,7 @@ class map
988988
//! <b>Complexity</b>: Logarithmic.
989989
template <class... Args>
990990
inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
991-
{ return this->base_t::try_emplace(const_iterator(), boost::move(k), boost::forward<Args>(args)...); }
991+
{ return this->base_t::try_emplace(boost::move(k), boost::forward<Args>(args)...); }
992992

993993
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
994994
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
@@ -1028,7 +1028,7 @@ class map
10281028
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool>
10291029
>::type)
10301030
try_emplace(BOOST_FWD_REF(K) k, BOOST_FWD_REF(Args)... args)
1031-
{ return this->base_t::try_emplace(const_iterator(), boost::forward<K>(k), boost::forward<Args>(args)...); }
1031+
{ return this->base_t::try_emplace(boost::forward<K>(k), boost::forward<Args>(args)...); }
10321032

10331033
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
10341034
//!
@@ -1066,15 +1066,15 @@ class map
10661066
\
10671067
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
10681068
inline std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1069-
{ return this->base_t::try_emplace(const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
1069+
{ return this->base_t::try_emplace(k BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
10701070
\
10711071
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
10721072
inline iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
10731073
{ return this->base_t::try_emplace(hint, k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first; }\
10741074
\
10751075
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
10761076
inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1077-
{ return this->base_t::try_emplace(const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
1077+
{ return this->base_t::try_emplace(boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
10781078
\
10791079
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
10801080
inline iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
@@ -1088,7 +1088,7 @@ class map
10881088
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> \
10891089
>::type \
10901090
try_emplace(BOOST_FWD_REF(K) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
1091-
{ return this->base_t::try_emplace(const_iterator() BOOST_MOVE_I boost::forward<K>(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); } \
1091+
{ return this->base_t::try_emplace(boost::forward<K>(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); } \
10921092
\
10931093
template <class K BOOST_MOVE_I##N BOOST_MOVE_CLASS##N> \
10941094
typename dtl::enable_if_transparent< key_compare \

0 commit comments

Comments
 (0)