1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___TYPE_TRAITS_IS_DESTRUCTIBLE_H
10#define _LIBCPP___TYPE_TRAITS_IS_DESTRUCTIBLE_H
11
12#include <__config>
13#include <__type_traits/integral_constant.h>
14#include <__type_traits/is_function.h>
15#include <__type_traits/is_reference.h>
16#include <__type_traits/remove_all_extents.h>
17#include <__utility/declval.h>
18
19#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20#  pragma GCC system_header
21#endif
22
23_LIBCPP_BEGIN_NAMESPACE_STD
24
25#if __has_builtin(__is_destructible)
26
27template <class _Tp>
28struct _LIBCPP_TEMPLATE_VIS is_destructible : _BoolConstant<__is_destructible(_Tp)> {};
29
30#  if _LIBCPP_STD_VER >= 17
31template <class _Tp>
32inline constexpr bool is_destructible_v = __is_destructible(_Tp);
33#  endif
34
35#else // __has_builtin(__is_destructible)
36
37//  if it's a reference, return true
38//  if it's a function, return false
39//  if it's   void,     return false
40//  if it's an array of unknown bound, return false
41//  Otherwise, return "declval<_Up&>().~_Up()" is well-formed
42//    where _Up is remove_all_extents<_Tp>::type
43
44template <class>
45struct __is_destructible_apply {
46  typedef int type;
47};
48
49template <typename _Tp>
50struct __is_destructor_wellformed {
51  template <typename _Tp1>
52  static true_type __test(typename __is_destructible_apply<decltype(std::declval<_Tp1&>().~_Tp1())>::type);
53
54  template <typename _Tp1>
55  static false_type __test(...);
56
57  static const bool value = decltype(__test<_Tp>(12))::value;
58};
59
60template <class _Tp, bool>
61struct __destructible_imp;
62
63template <class _Tp>
64struct __destructible_imp<_Tp, false>
65    : public integral_constant<bool, __is_destructor_wellformed<__remove_all_extents_t<_Tp> >::value> {};
66
67template <class _Tp>
68struct __destructible_imp<_Tp, true> : public true_type {};
69
70template <class _Tp, bool>
71struct __destructible_false;
72
73template <class _Tp>
74struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, is_reference<_Tp>::value> {};
75
76template <class _Tp>
77struct __destructible_false<_Tp, true> : public false_type {};
78
79template <class _Tp>
80struct is_destructible : public __destructible_false<_Tp, is_function<_Tp>::value> {};
81
82template <class _Tp>
83struct is_destructible<_Tp[]> : public false_type {};
84
85template <>
86struct is_destructible<void> : public false_type {};
87
88#  if _LIBCPP_STD_VER >= 17
89template <class _Tp>
90inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
91#  endif
92
93#endif // __has_builtin(__is_destructible)
94
95_LIBCPP_END_NAMESPACE_STD
96
97#endif // _LIBCPP___TYPE_TRAITS_IS_DESTRUCTIBLE_H
98