diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 0ae031e5365ae..2bb6d263340d3 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -761,6 +761,7 @@ set(files __type_traits/decay.h __type_traits/dependent_type.h __type_traits/desugars_to.h + __type_traits/detected_or.h __type_traits/disjunction.h __type_traits/enable_if.h __type_traits/extent.h diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index 499b30b85b6c9..62b454c922752 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -15,6 +15,7 @@ #include <__fwd/memory.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> +#include <__type_traits/detected_or.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_empty.h> @@ -42,17 +43,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct NAME<_Tp, __void_t > : true_type {} // __pointer -template , - bool = __has_pointer<_RawAlloc>::value> -struct __pointer { - using type _LIBCPP_NODEBUG = typename _RawAlloc::pointer; -}; -template -struct __pointer<_Tp, _Alloc, _RawAlloc, false> { - using type _LIBCPP_NODEBUG = _Tp*; -}; +template +using __pointer_member = typename _Tp::pointer; + +template +using __pointer = __detected_or_t<_Tp*, __pointer_member, __libcpp_remove_reference_t<_Alloc> >; // __const_pointer _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_pointer, const_pointer); @@ -100,13 +95,11 @@ struct __const_void_pointer<_Ptr, _Alloc, false> { }; // __size_type -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_size_type, size_type); -template ::value> -struct __size_type : make_unsigned<_DiffType> {}; +template +using __size_type_member = typename _Tp::size_type; + template -struct __size_type<_Alloc, _DiffType, true> { - using type _LIBCPP_NODEBUG = typename _Alloc::size_type; -}; +using __size_type = __detected_or_t<__make_unsigned_t<_DiffType>, __size_type_member, _Alloc>; // __alloc_traits_difference_type _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_alloc_traits_difference_type, difference_type); @@ -120,40 +113,34 @@ struct __alloc_traits_difference_type<_Alloc, _Ptr, true> { }; // __propagate_on_container_copy_assignment -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_copy_assignment, propagate_on_container_copy_assignment); -template ::value> -struct __propagate_on_container_copy_assignment : false_type {}; +template +using __propagate_on_container_copy_assignment_member = typename _Tp::propagate_on_container_copy_assignment; + template -struct __propagate_on_container_copy_assignment<_Alloc, true> { - using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_copy_assignment; -}; +using __propagate_on_container_copy_assignment = + __detected_or_t; // __propagate_on_container_move_assignment -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_move_assignment, propagate_on_container_move_assignment); -template ::value> -struct __propagate_on_container_move_assignment : false_type {}; +template +using __propagate_on_container_move_assignment_member = typename _Tp::propagate_on_container_move_assignment; + template -struct __propagate_on_container_move_assignment<_Alloc, true> { - using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_move_assignment; -}; +using __propagate_on_container_move_assignment = + __detected_or_t; // __propagate_on_container_swap -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_swap, propagate_on_container_swap); -template ::value> -struct __propagate_on_container_swap : false_type {}; +template +using __propagate_on_container_swap_member = typename _Tp::propagate_on_container_swap; + template -struct __propagate_on_container_swap<_Alloc, true> { - using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_swap; -}; +using __propagate_on_container_swap = __detected_or_t; // __is_always_equal -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_is_always_equal, is_always_equal); -template ::value> -struct __is_always_equal : is_empty<_Alloc> {}; +template +using __is_always_equal_member = typename _Tp::is_always_equal; + template -struct __is_always_equal<_Alloc, true> { - using type _LIBCPP_NODEBUG = typename _Alloc::is_always_equal; -}; +using __is_always_equal = __detected_or_t::type, __is_always_equal_member, _Alloc>; // __allocator_traits_rebind _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -245,20 +232,18 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result); template struct _LIBCPP_TEMPLATE_VIS allocator_traits { - using allocator_type = _Alloc; - using value_type = typename allocator_type::value_type; - using pointer = typename __pointer::type; - using const_pointer = typename __const_pointer::type; - using void_pointer = typename __void_pointer::type; - using const_void_pointer = typename __const_void_pointer::type; - using difference_type = typename __alloc_traits_difference_type::type; - using size_type = typename __size_type::type; - using propagate_on_container_copy_assignment = - typename __propagate_on_container_copy_assignment::type; - using propagate_on_container_move_assignment = - typename __propagate_on_container_move_assignment::type; - using propagate_on_container_swap = typename __propagate_on_container_swap::type; - using is_always_equal = typename __is_always_equal::type; + using allocator_type = _Alloc; + using value_type = typename allocator_type::value_type; + using pointer = __pointer; + using const_pointer = typename __const_pointer::type; + using void_pointer = typename __void_pointer::type; + using const_void_pointer = typename __const_void_pointer::type; + using difference_type = typename __alloc_traits_difference_type::type; + using size_type = __size_type; + using propagate_on_container_copy_assignment = __propagate_on_container_copy_assignment; + using propagate_on_container_move_assignment = __propagate_on_container_move_assignment; + using propagate_on_container_swap = __propagate_on_container_swap; + using is_always_equal = __is_always_equal; #ifndef _LIBCPP_CXX03_LANG template diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 28c62e13566e2..9526255583dd5 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -143,7 +143,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { public: typedef _Tp element_type; typedef _Dp deleter_type; - typedef _LIBCPP_NODEBUG typename __pointer<_Tp, deleter_type>::type pointer; + using pointer _LIBCPP_NODEBUG = __pointer<_Tp, deleter_type>; static_assert(!is_rvalue_reference::value, "the specified deleter type cannot be an rvalue reference"); @@ -410,7 +410,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> public: typedef _Tp element_type; typedef _Dp deleter_type; - typedef typename __pointer<_Tp, deleter_type>::type pointer; + using pointer = __pointer<_Tp, deleter_type>; // A unique_ptr contains the following members which may be trivially relocatable: // - pointer: this may be trivially relocatable, so it's checked diff --git a/libcxx/include/__type_traits/detected_or.h b/libcxx/include/__type_traits/detected_or.h new file mode 100644 index 0000000000000..390f368411471 --- /dev/null +++ b/libcxx/include/__type_traits/detected_or.h @@ -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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_DETECTED_OR_H +#define _LIBCPP___TYPE_TRAITS_DETECTED_OR_H + +#include <__config> +#include <__type_traits/void_t.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class _Op, class... _Args> +struct __detector { + using type = _Default; +}; + +template class _Op, class... _Args> +struct __detector<_Default, __void_t<_Op<_Args...> >, _Op, _Args...> { + using type = _Op<_Args...>; +}; + +template class _Op, class... _Args> +using __detected_or_t = typename __detector<_Default, void, _Op, _Args...>::type; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_DETECTED_OR_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 4e06a68c6a6b6..ed2b7fb192164 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -87,6 +87,7 @@ module std_core [system] { module decay { header "__type_traits/decay.h" } module dependent_type { header "__type_traits/dependent_type.h" } module desugars_to { header "__type_traits/desugars_to.h" } + module detected_or { header "__type_traits/detected_or.h" } module disjunction { header "__type_traits/disjunction.h" } module enable_if { header "__type_traits/enable_if.h" } module extent { header "__type_traits/extent.h" }