Skip to content

Commit c448834

Browse files
Allow runtime decision for __assign_value
1 parent c28aac0 commit c448834

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

libcxx/include/__tree

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,14 +1360,35 @@ private:
13601360
}
13611361
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
13621362

1363+
1364+
template <class _From, class _ValueT = _Tp, __enable_if_t<__is_tree_value_type_v<_ValueT>, int> = 0>
1365+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
1366+
__assign_value__sfinae(true_type, __get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
1367+
1368+
__node_allocator& __na = __node_alloc();
1369+
__node_traits::destroy(__na, std::addressof(__lhs));
1370+
1371+
using __node_value_type = __get_node_value_type_t<value_type>;
1372+
__node_value_type __tmp(__rhs.first, __rhs.second);
1373+
1374+
__node_traits::construct(__na, std::addressof(__lhs), std::move(__tmp));
1375+
1376+
}
1377+
1378+
template <class _From, class _ValueT = _Tp, __enable_if_t<__is_tree_value_type_v<_ValueT>, int> = 0>
1379+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
1380+
__assign_value__sfinae(false_type, __get_node_value_type_t<value_type>& , _From&& ) {
1381+
// This method body should never be run. It only exists to allow for compilation. See note in __assign_value for more information
1382+
}
1383+
13631384
template <class _From, class _ValueT = _Tp, __enable_if_t<__is_tree_value_type_v<_ValueT>, int> = 0>
13641385
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
13651386
__assign_value(__get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
13661387
using __key_type = __remove_const_t<typename value_type::first_type>;
13671388

13681389
#if _LIBCPP_STD_VER >= 26
13691390

1370-
if constexpr (std::is_copy_constructible_v<decltype(__rhs.first)>) {
1391+
if (std::is_constant_evaluated() && std::is_copy_constructible_v<decltype(__rhs.first)>) {
13711392
// we use copy, and not "move" as the constraint
13721393
// because we can NOT move from `const key_type`, which is how `value_type` is defined
13731394
// atleast for map
@@ -1378,13 +1399,17 @@ private:
13781399
// we get around this by deleting __lhs and creating a new node in-place
13791400
// to avoid const_cast __lhs.first
13801401

1381-
__node_allocator& __na = __node_alloc();
1382-
__node_traits::destroy(__na, std::addressof(__lhs));
1402+
// We create a sfinae wrapper method here, because if the body of the true_type overload for __assign_value__sfinae() gets template instantiated within __assign_value,
1403+
// the code will fail to compile where the value is not copy_constructible for runtime execution as well; unless we use `if constexpr`.
1404+
// Given the copy-constructible code path will be a performance regression, we want to restrict it to only execute during constant evaluation
1405+
//, we need to delay the template instantiation
13831406

1384-
using __node_value_type = __get_node_value_type_t<value_type>;
1385-
__node_value_type __tmp(__rhs.first, __rhs.second);
1407+
__assign_value__sfinae(
1408+
std::integral_constant<bool, std::is_copy_constructible_v<decltype(__rhs.first)>>(),
1409+
std::forward<decltype(__lhs)>(__lhs),
1410+
std::forward<decltype(__rhs)>(__rhs)
1411+
);
13861412

1387-
__node_traits::construct(__na, std::addressof(__lhs), std::move(__tmp));
13881413

13891414
} else
13901415
#endif

0 commit comments

Comments
 (0)