aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/experimental/type_traits
blob: 7ab097226b5d65f407f9d2971da0ebce9fdb7f39 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// -*- C++ -*-
//===-------------------------- type_traits -------------------------------===//
//
// 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_EXPERIMENTAL_TYPE_TRAITS
#define _LIBCPP_EXPERIMENTAL_TYPE_TRAITS

/**
    experimental/type_traits synopsis

// C++1y
#include <type_traits>

namespace std {
namespace experimental {
inline namespace fundamentals_v1 {

  // 3.3.2, Other type transformations
  template <class> class invocation_type; // not defined
  template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>;
  template <class> class raw_invocation_type; // not defined
  template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>;

  template <class T>
    using invocation_type_t = typename invocation_type<T>::type;
  template <class T>
    using raw_invocation_type_t = typename raw_invocation_type<T>::type;

  // 3.3.4, Detection idiom
  template <class...> using void_t = void;

  struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&) = delete;
    void operator=(nonesuch const&) = delete;
  };

  template <template<class...> class Op, class... Args>
    using is_detected = see below;
  template <template<class...> class Op, class... Args>
    constexpr bool is_detected_v = is_detected<Op, Args...>::value;
  template <template<class...> class Op, class... Args>
    using detected_t = see below;
  template <class Default, template<class...> class Op, class... Args>
    using detected_or = see below;
  template <class Default, template<class...> class Op, class... Args>
    using detected_or_t = typename detected_or<Default, Op, Args...>::type;
  template <class Expected, template<class...> class Op, class... Args>
    using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>;
  template <class Expected, template<class...> class Op, class... Args>
    constexpr bool is_detected_exact_v
      = is_detected_exact<Expected, Op, Args...>::value;
  template <class To, template<class...> class Op, class... Args>
     using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>;
  template <class To, template<class...> class Op, class... Args>
     constexpr bool is_detected_convertible_v
       = is_detected_convertible<To, Op, Args...>::value;

} // namespace fundamentals_v1
} // namespace experimental
} // namespace std

 */

#include <experimental/__config>

#if _LIBCPP_STD_VER > 11

#include <initializer_list>
#include <type_traits>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_LFTS

// 3.3.2, Other type transformations
/*
template <class>
class _LIBCPP_TEMPLATE_VIS raw_invocation_type;

template <class _Fn, class ..._Args>
class _LIBCPP_TEMPLATE_VIS raw_invocation_type<_Fn(_Args...)>;

template <class>
class _LIBCPP_TEMPLATE_VIS invokation_type;

template <class _Fn, class ..._Args>
class _LIBCPP_TEMPLATE_VIS invokation_type<_Fn(_Args...)>;

template <class _Tp>
using invokation_type_t = typename invokation_type<_Tp>::type;

template <class _Tp>
using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type;
*/

// 3.3.4, Detection idiom
template <class...> using void_t = void;

struct nonesuch : private _VSTD::__nat { // make nonesuch "not an aggregate"
  ~nonesuch() = delete;
  nonesuch      (nonesuch const&) = delete;
  void operator=(nonesuch const&) = delete;
  };

template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args>
struct _DETECTOR {
   using value_t = false_type;
   using type = _Default;
   };

template <class _Default, template <class...> class _Op, class... _Args>
struct _DETECTOR<_Default, void_t<_Op<_Args...>>, _Op, _Args...> {
   using value_t = true_type;
   using type = _Op<_Args...>;
   };


template <template<class...> class _Op, class... _Args>
  using is_detected = typename _DETECTOR<nonesuch, void, _Op, _Args...>::value_t;
template <template<class...> class _Op, class... _Args>
  using detected_t = typename _DETECTOR<nonesuch, void, _Op, _Args...>::type;
template <template<class...> class _Op, class... _Args>
  _LIBCPP_CONSTEXPR bool is_detected_v = is_detected<_Op, _Args...>::value;

template <class Default, template<class...> class _Op, class... _Args>
  using detected_or = _DETECTOR<Default, void, _Op, _Args...>;
template <class Default, template<class...> class _Op, class... _Args>
  using detected_or_t = typename detected_or<Default, _Op, _Args...>::type;

template <class Expected, template<class...> class _Op, class... _Args>
  using is_detected_exact = is_same<Expected, detected_t<_Op, _Args...>>;
template <class Expected, template<class...> class _Op, class... _Args>
  _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, _Op, _Args...>::value;

template <class To, template<class...> class _Op, class... _Args>
  using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, To>;
template <class To, template<class...> class _Op, class... _Args>
  _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, _Op, _Args...>::value;


_LIBCPP_END_NAMESPACE_LFTS

#endif /* _LIBCPP_STD_VER > 11 */

#endif /* _LIBCPP_EXPERIMENTAL_TYPE_TRAITS */