diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h index 8dd0721f2c65f..4332b62544b40 100644 --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -34,7 +34,6 @@ #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_same.h> #include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/remove_cvref.h> #include <__utility/move.h> #include <__utility/pair.h> #include @@ -52,8 +51,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template ::value_type> inline const bool __use_branchless_sort = __libcpp_is_contiguous_iterator<_Iter>::value && __is_cheap_to_copy<_Tp> && is_arithmetic<_Tp>::value && - (__desugars_to_v<__less_tag, __remove_cvref_t<_Compare>, _Tp, _Tp> || - __desugars_to_v<__greater_tag, __remove_cvref_t<_Compare>, _Tp, _Tp>); + (__desugars_to_v<__less_tag, _Compare, _Tp, _Tp> || __desugars_to_v<__greater_tag, _Compare, _Tp, _Tp>); namespace __detail { diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h index 76d9e5557008f..c7f9780e3f627 100644 --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -29,7 +29,6 @@ #include <__type_traits/is_integral.h> #include <__type_traits/is_same.h> #include <__type_traits/is_trivially_assignable.h> -#include <__type_traits/remove_cvref.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -246,8 +245,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort( } #if _LIBCPP_STD_VER >= 17 - constexpr auto __default_comp = - __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >; + constexpr auto __default_comp = __desugars_to_v<__totally_ordered_less_tag, _Compare, value_type, value_type >; constexpr auto __integral_value = is_integral_v && is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>; constexpr auto __allowed_radix_sort = __default_comp && __integral_value; diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h index d6cd6428f22db..3678b5553c444 100644 --- a/libcxx/include/__functional/reference_wrapper.h +++ b/libcxx/include/__functional/reference_wrapper.h @@ -15,6 +15,7 @@ #include <__config> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> +#include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> @@ -149,6 +150,11 @@ void ref(const _Tp&&) = delete; template void cref(const _Tp&&) = delete; +// Let desugars-to pass through std::reference_wrapper +template +inline const bool __desugars_to_v<_CanonicalTag, reference_wrapper<_Operation>, _Args...> = + __desugars_to_v<_CanonicalTag, _Operation, _Args...>; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H diff --git a/libcxx/include/__type_traits/desugars_to.h b/libcxx/include/__type_traits/desugars_to.h index 452c70bfbad66..b67baae31b181 100644 --- a/libcxx/include/__type_traits/desugars_to.h +++ b/libcxx/include/__type_traits/desugars_to.h @@ -52,6 +52,18 @@ struct __totally_ordered_less_tag {}; template inline const bool __desugars_to_v = false; +// For the purpose of determining whether something desugars to something else, +// we disregard const and ref qualifiers on the operation itself. +template +inline const bool __desugars_to_v<_CanonicalTag, _Operation const, _Args...> = + __desugars_to_v<_CanonicalTag, _Operation, _Args...>; +template +inline const bool __desugars_to_v<_CanonicalTag, _Operation&, _Args...> = + __desugars_to_v<_CanonicalTag, _Operation, _Args...>; +template +inline const bool __desugars_to_v<_CanonicalTag, _Operation&&, _Args...> = + __desugars_to_v<_CanonicalTag, _Operation, _Args...>; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_DESUGARS_TO_H diff --git a/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp b/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp new file mode 100644 index 0000000000000..4ed6d15ee9e95 --- /dev/null +++ b/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME + +// This test requires variable templates +// UNSUPPORTED: gcc && c++11 + +#include <__type_traits/desugars_to.h> + +struct Tag {}; +struct Operation {}; + +namespace std { +template <> +bool const __desugars_to_v = true; +} + +void tests() { + // Make sure that __desugars_to is false by default + { + struct Foo {}; + static_assert(!std::__desugars_to_v, ""); + } + + // Make sure that __desugars_to bypasses const and ref qualifiers on the operation + { + static_assert(std::__desugars_to_v, ""); // no quals + static_assert(std::__desugars_to_v, ""); + + static_assert(std::__desugars_to_v, ""); + static_assert(std::__desugars_to_v, ""); + + static_assert(std::__desugars_to_v, ""); + static_assert(std::__desugars_to_v, ""); + } +} diff --git a/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp b/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp new file mode 100644 index 0000000000000..1ce88feeadf28 --- /dev/null +++ b/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME + +// This test requires variable templates +// UNSUPPORTED: gcc && c++11 + +// + +// reference_wrapper + +// Ensure that std::reference_wrapper does not inhibit optimizations based on the +// std::__desugars_to internal helper. + +#include +#include <__type_traits/desugars_to.h> + +struct Operation {}; +struct Tag {}; + +namespace std { +template <> +bool const __desugars_to_v = true; +} + +static_assert(std::__desugars_to_v, "something is wrong with the test"); + +// make sure we pass through reference_wrapper +static_assert(std::__desugars_to_v >, ""); +static_assert(std::__desugars_to_v >, "");