Skip to content

[libc++] Add __detected_or_t and use it to implement some of the allocator traits aliases #115654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
95 changes: 40 additions & 55 deletions libcxx/include/__memory/allocator_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -42,17 +43,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {}

// __pointer
template <class _Tp,
class _Alloc,
class _RawAlloc = __libcpp_remove_reference_t<_Alloc>,
bool = __has_pointer<_RawAlloc>::value>
struct __pointer {
using type _LIBCPP_NODEBUG = typename _RawAlloc::pointer;
};
template <class _Tp, class _Alloc, class _RawAlloc>
struct __pointer<_Tp, _Alloc, _RawAlloc, false> {
using type _LIBCPP_NODEBUG = _Tp*;
};
template <class _Tp>
using __pointer_member = typename _Tp::pointer;

template <class _Tp, class _Alloc>
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);
Expand Down Expand Up @@ -100,13 +95,11 @@ struct __const_void_pointer<_Ptr, _Alloc, false> {
};

// __size_type
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_size_type, size_type);
template <class _Alloc, class _DiffType, bool = __has_size_type<_Alloc>::value>
struct __size_type : make_unsigned<_DiffType> {};
template <class _Tp>
using __size_type_member = typename _Tp::size_type;

template <class _Alloc, class _DiffType>
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);
Expand All @@ -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 <class _Alloc, bool = __has_propagate_on_container_copy_assignment<_Alloc>::value>
struct __propagate_on_container_copy_assignment : false_type {};
template <class _Tp>
using __propagate_on_container_copy_assignment_member = typename _Tp::propagate_on_container_copy_assignment;

template <class _Alloc>
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<false_type, __propagate_on_container_copy_assignment_member, _Alloc>;

// __propagate_on_container_move_assignment
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_move_assignment, propagate_on_container_move_assignment);
template <class _Alloc, bool = __has_propagate_on_container_move_assignment<_Alloc>::value>
struct __propagate_on_container_move_assignment : false_type {};
template <class _Tp>
using __propagate_on_container_move_assignment_member = typename _Tp::propagate_on_container_move_assignment;

template <class _Alloc>
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<false_type, __propagate_on_container_move_assignment_member, _Alloc>;

// __propagate_on_container_swap
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_swap, propagate_on_container_swap);
template <class _Alloc, bool = __has_propagate_on_container_swap<_Alloc>::value>
struct __propagate_on_container_swap : false_type {};
template <class _Tp>
using __propagate_on_container_swap_member = typename _Tp::propagate_on_container_swap;

template <class _Alloc>
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<false_type, __propagate_on_container_swap_member, _Alloc>;

// __is_always_equal
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_is_always_equal, is_always_equal);
template <class _Alloc, bool = __has_is_always_equal<_Alloc>::value>
struct __is_always_equal : is_empty<_Alloc> {};
template <class _Tp>
using __is_always_equal_member = typename _Tp::is_always_equal;

template <class _Alloc>
struct __is_always_equal<_Alloc, true> {
using type _LIBCPP_NODEBUG = typename _Alloc::is_always_equal;
};
using __is_always_equal = __detected_or_t<typename is_empty<_Alloc>::type, __is_always_equal_member, _Alloc>;

// __allocator_traits_rebind
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Expand Down Expand Up @@ -245,20 +232,18 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);

template <class _Alloc>
struct _LIBCPP_TEMPLATE_VIS allocator_traits {
using allocator_type = _Alloc;
using value_type = typename allocator_type::value_type;
using pointer = typename __pointer<value_type, allocator_type>::type;
using const_pointer = typename __const_pointer<value_type, pointer, allocator_type>::type;
using void_pointer = typename __void_pointer<pointer, allocator_type>::type;
using const_void_pointer = typename __const_void_pointer<pointer, allocator_type>::type;
using difference_type = typename __alloc_traits_difference_type<allocator_type, pointer>::type;
using size_type = typename __size_type<allocator_type, difference_type>::type;
using propagate_on_container_copy_assignment =
typename __propagate_on_container_copy_assignment<allocator_type>::type;
using propagate_on_container_move_assignment =
typename __propagate_on_container_move_assignment<allocator_type>::type;
using propagate_on_container_swap = typename __propagate_on_container_swap<allocator_type>::type;
using is_always_equal = typename __is_always_equal<allocator_type>::type;
using allocator_type = _Alloc;
using value_type = typename allocator_type::value_type;
using pointer = __pointer<value_type, allocator_type>;
using const_pointer = typename __const_pointer<value_type, pointer, allocator_type>::type;
using void_pointer = typename __void_pointer<pointer, allocator_type>::type;
using const_void_pointer = typename __const_void_pointer<pointer, allocator_type>::type;
using difference_type = typename __alloc_traits_difference_type<allocator_type, pointer>::type;
using size_type = __size_type<allocator_type, difference_type>;
using propagate_on_container_copy_assignment = __propagate_on_container_copy_assignment<allocator_type>;
using propagate_on_container_move_assignment = __propagate_on_container_move_assignment<allocator_type>;
using propagate_on_container_swap = __propagate_on_container_swap<allocator_type>;
using is_always_equal = __is_always_equal<allocator_type>;

#ifndef _LIBCPP_CXX03_LANG
template <class _Tp>
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__memory/unique_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<deleter_type>::value, "the specified deleter type cannot be an rvalue reference");

Expand Down Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions libcxx/include/__type_traits/detected_or.h
Original file line number Diff line number Diff line change
@@ -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 _Default, class _Void, template <class...> class _Op, class... _Args>
struct __detector {
using type = _Default;
};

template <class _Default, template <class...> class _Op, class... _Args>
struct __detector<_Default, __void_t<_Op<_Args...> >, _Op, _Args...> {
using type = _Op<_Args...>;
};

template <class _Default, template <class...> 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
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
Loading