3 // Copyright Michael Park, 2015-2017
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
13 #include <type_traits>
19 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \
26 struct identity
{ using type
= T
; };
28 inline namespace cpp14
{
29 template <typename T
, std::size_t N
>
31 constexpr const T
&operator[](std::size_t index
) const {
35 T data
[N
== 0 ? 1 : N
];
39 using add_pointer_t
= typename
std::add_pointer
<T
>::type
;
41 template <typename
... Ts
>
42 using common_type_t
= typename
std::common_type
<Ts
...>::type
;
45 using decay_t
= typename
std::decay
<T
>::type
;
47 template <bool B
, typename T
= void>
48 using enable_if_t
= typename
std::enable_if
<B
, T
>::type
;
51 using remove_const_t
= typename
std::remove_const
<T
>::type
;
54 using remove_reference_t
= typename
std::remove_reference
<T
>::type
;
57 inline constexpr T
&&forward(remove_reference_t
<T
> &t
) noexcept
{
58 return static_cast<T
&&>(t
);
62 inline constexpr T
&&forward(remove_reference_t
<T
> &&t
) noexcept
{
63 static_assert(!std::is_lvalue_reference
<T
>::value
,
64 "can not forward an rvalue as an lvalue");
65 return static_cast<T
&&>(t
);
69 inline constexpr remove_reference_t
<T
> &&move(T
&&t
) noexcept
{
70 return static_cast<remove_reference_t
<T
> &&>(t
);
73 #ifdef MPARK_INTEGER_SEQUENCE
74 using std::integer_sequence
;
75 using std::index_sequence
;
76 using std::make_index_sequence
;
77 using std::index_sequence_for
;
79 template <typename T
, T
... Is
>
80 struct integer_sequence
{
82 static constexpr std::size_t size() noexcept
{ return sizeof...(Is
); }
85 template <std::size_t... Is
>
86 using index_sequence
= integer_sequence
<std::size_t, Is
...>;
88 template <typename Lhs
, typename Rhs
>
89 struct make_index_sequence_concat
;
91 template <std::size_t... Lhs
, std::size_t... Rhs
>
92 struct make_index_sequence_concat
<index_sequence
<Lhs
...>,
93 index_sequence
<Rhs
...>>
94 : identity
<index_sequence
<Lhs
..., (sizeof...(Lhs
) + Rhs
)...>> {};
96 template <std::size_t N
>
97 struct make_index_sequence_impl
;
99 template <std::size_t N
>
100 using make_index_sequence
= typename make_index_sequence_impl
<N
>::type
;
102 template <std::size_t N
>
103 struct make_index_sequence_impl
104 : make_index_sequence_concat
<make_index_sequence
<N
/ 2>,
105 make_index_sequence
<N
- (N
/ 2)>> {};
108 struct make_index_sequence_impl
<0> : identity
<index_sequence
<>> {};
111 struct make_index_sequence_impl
<1> : identity
<index_sequence
<0>> {};
113 template <typename
... Ts
>
114 using index_sequence_for
= make_index_sequence
<sizeof...(Ts
)>;
118 #ifdef MPARK_TRANSPARENT_OPERATORS
119 using equal_to
= std::equal_to
<>;
122 template <typename Lhs
, typename Rhs
>
123 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
124 RETURN(lib::forward
<Lhs
>(lhs
) == lib::forward
<Rhs
>(rhs
))
128 #ifdef MPARK_TRANSPARENT_OPERATORS
129 using not_equal_to
= std::not_equal_to
<>;
131 struct not_equal_to
{
132 template <typename Lhs
, typename Rhs
>
133 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
134 RETURN(lib::forward
<Lhs
>(lhs
) != lib::forward
<Rhs
>(rhs
))
138 #ifdef MPARK_TRANSPARENT_OPERATORS
139 using less
= std::less
<>;
142 template <typename Lhs
, typename Rhs
>
143 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
144 RETURN(lib::forward
<Lhs
>(lhs
) < lib::forward
<Rhs
>(rhs
))
148 #ifdef MPARK_TRANSPARENT_OPERATORS
149 using greater
= std::greater
<>;
152 template <typename Lhs
, typename Rhs
>
153 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
154 RETURN(lib::forward
<Lhs
>(lhs
) > lib::forward
<Rhs
>(rhs
))
158 #ifdef MPARK_TRANSPARENT_OPERATORS
159 using less_equal
= std::less_equal
<>;
162 template <typename Lhs
, typename Rhs
>
163 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
164 RETURN(lib::forward
<Lhs
>(lhs
) <= lib::forward
<Rhs
>(rhs
))
168 #ifdef MPARK_TRANSPARENT_OPERATORS
169 using greater_equal
= std::greater_equal
<>;
171 struct greater_equal
{
172 template <typename Lhs
, typename Rhs
>
173 inline constexpr auto operator()(Lhs
&&lhs
, Rhs
&&rhs
) const
174 RETURN(lib::forward
<Lhs
>(lhs
) >= lib::forward
<Rhs
>(rhs
))
179 inline namespace cpp17
{
183 using bool_constant
= std::integral_constant
<bool, B
>;
185 template <typename
...>
186 struct voider
: identity
<void> {};
188 template <typename
... Ts
>
189 using void_t
= typename voider
<Ts
...>::type
;
192 namespace swappable
{
196 template <typename T
>
197 struct is_swappable_impl
{
199 template <typename U
,
200 typename
= decltype(swap(std::declval
<U
&>(),
201 std::declval
<U
&>()))>
202 inline static std::true_type
test(int);
204 template <typename U
>
205 inline static std::false_type
test(...);
208 using type
= decltype(test
<T
>(0));
211 template <typename T
>
212 using is_swappable
= typename is_swappable_impl
<T
>::type
;
214 template <typename T
, bool = is_swappable
<T
>::value
>
215 struct is_nothrow_swappable
{
216 static constexpr bool value
=
217 noexcept(swap(std::declval
<T
&>(), std::declval
<T
&>()));
220 template <typename T
>
221 struct is_nothrow_swappable
<T
, false> : std::false_type
{};
223 } // namespace swappable
224 } // namespace detail
226 template <typename T
>
227 using is_swappable
= detail::swappable::is_swappable
<T
>;
229 template <typename T
>
230 using is_nothrow_swappable
= detail::swappable::is_nothrow_swappable
<T
>;
234 #pragma warning(push)
235 #pragma warning(disable : 4100)
237 template <typename F
, typename
... As
>
238 inline constexpr auto invoke(F
&&f
, As
&&... as
)
239 RETURN(lib::forward
<F
>(f
)(lib::forward
<As
>(as
)...))
244 template <typename B
, typename T
, typename D
>
245 inline constexpr auto invoke(T
B::*pmv
, D
&&d
)
246 RETURN(lib::forward
<D
>(d
).*pmv
)
248 template <typename Pmv
, typename Ptr
>
249 inline constexpr auto invoke(Pmv pmv
, Ptr
&&ptr
)
250 RETURN((*lib::forward
<Ptr
>(ptr
)).*pmv
)
252 template <typename B
, typename T
, typename D
, typename
... As
>
253 inline constexpr auto invoke(T
B::*pmf
, D
&&d
, As
&&... as
)
254 RETURN((lib::forward
<D
>(d
).*pmf
)(lib::forward
<As
>(as
)...))
256 template <typename Pmf
, typename Ptr
, typename
... As
>
257 inline constexpr auto invoke(Pmf pmf
, Ptr
&&ptr
, As
&&... as
)
258 RETURN(((*lib::forward
<Ptr
>(ptr
)).*pmf
)(lib::forward
<As
>(as
)...))
262 template <typename Void
, typename
, typename
...>
263 struct invoke_result
{};
265 template <typename F
, typename
... Args
>
266 struct invoke_result
<void_t
<decltype(lib::invoke(
267 std::declval
<F
>(), std::declval
<Args
>()...))>,
271 lib::invoke(std::declval
<F
>(), std::declval
<Args
>()...))> {};
273 } // namespace detail
275 template <typename F
, typename
... Args
>
276 using invoke_result
= detail::invoke_result
<void, F
, Args
...>;
278 template <typename F
, typename
... Args
>
279 using invoke_result_t
= typename invoke_result
<F
, Args
...>::type
;
283 template <typename Void
, typename
, typename
...>
284 struct is_invocable
: std::false_type
{};
286 template <typename F
, typename
... Args
>
287 struct is_invocable
<void_t
<invoke_result_t
<F
, Args
...>>, F
, Args
...>
290 template <typename Void
, typename
, typename
, typename
...>
291 struct is_invocable_r
: std::false_type
{};
293 template <typename R
, typename F
, typename
... Args
>
294 struct is_invocable_r
<void_t
<invoke_result_t
<F
, Args
...>>,
298 : std::is_convertible
<invoke_result_t
<F
, Args
...>, R
> {};
300 } // namespace detail
302 template <typename F
, typename
... Args
>
303 using is_invocable
= detail::is_invocable
<void, F
, Args
...>;
305 template <typename R
, typename F
, typename
... Args
>
306 using is_invocable_r
= detail::is_invocable_r
<void, R
, F
, Args
...>;
309 #ifdef MPARK_BUILTIN_ADDRESSOF
310 template <typename T
>
311 inline constexpr T
*addressof(T
&arg
) {
312 return __builtin_addressof(arg
);
317 namespace has_addressof_impl
{
321 template <typename T
>
322 inline fail
operator&(T
&&);
324 template <typename T
>
325 inline static constexpr bool impl() {
326 return (std::is_class
<T
>::value
|| std::is_union
<T
>::value
) &&
327 !std::is_same
<decltype(&std::declval
<T
&>()), fail
>::value
;
330 } // namespace has_addressof_impl
332 template <typename T
>
333 using has_addressof
= bool_constant
<has_addressof_impl::impl
<T
>()>;
335 template <typename T
>
336 inline constexpr T
*addressof(T
&arg
, std::true_type
) {
337 return std::addressof(arg
);
340 template <typename T
>
341 inline constexpr T
*addressof(T
&arg
, std::false_type
) {
345 } // namespace detail
347 template <typename T
>
348 inline constexpr T
*addressof(T
&arg
) {
349 return detail::addressof(arg
, detail::has_addressof
<T
>{});
353 template <typename T
>
354 inline constexpr T
*addressof(const T
&&) = delete;
358 template <typename T
>
359 struct remove_all_extents
: identity
<T
> {};
361 template <typename T
, std::size_t N
>
362 struct remove_all_extents
<array
<T
, N
>> : remove_all_extents
<T
> {};
364 template <typename T
>
365 using remove_all_extents_t
= typename remove_all_extents
<T
>::type
;
367 template <std::size_t N
>
368 using size_constant
= std::integral_constant
<std::size_t, N
>;
370 template <bool... Bs
>
371 using bool_sequence
= integer_sequence
<bool, Bs
...>;
373 template <std::size_t I
, typename T
>
374 struct indexed_type
: size_constant
<I
>, identity
<T
> {};
376 template <bool... Bs
>
378 std::is_same
<bool_sequence
<true, Bs
...>, bool_sequence
<Bs
..., true>>;
380 #ifdef MPARK_TYPE_PACK_ELEMENT
381 template <std::size_t I
, typename
... Ts
>
382 using type_pack_element_t
= __type_pack_element
<I
, Ts
...>;
384 template <std::size_t I
, typename
... Ts
>
385 struct type_pack_element_impl
{
390 template <std::size_t... Is
>
391 struct set
<index_sequence
<Is
...>> : indexed_type
<Is
, Ts
>... {};
393 template <typename T
>
394 inline static std::enable_if
<true, T
> impl(indexed_type
<I
, T
>);
396 inline static std::enable_if
<false> impl(...);
399 using type
= decltype(impl(set
<index_sequence_for
<Ts
...>>{}));
402 template <std::size_t I
, typename
... Ts
>
403 using type_pack_element
= typename type_pack_element_impl
<I
, Ts
...>::type
;
405 template <std::size_t I
, typename
... Ts
>
406 using type_pack_element_t
= typename type_pack_element
<I
, Ts
...>::type
;
409 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
410 using std::is_trivially_copy_constructible
;
411 using std::is_trivially_move_constructible
;
412 using std::is_trivially_copy_assignable
;
413 using std::is_trivially_move_assignable
;
415 template <typename T
>
416 struct is_trivially_copy_constructible
418 std::is_copy_constructible
<T
>::value
&& __has_trivial_copy(T
)> {};
420 template <typename T
>
421 struct is_trivially_move_constructible
: bool_constant
<__is_trivial(T
)> {};
423 template <typename T
>
424 struct is_trivially_copy_assignable
426 std::is_copy_assignable
<T
>::value
&& __has_trivial_assign(T
)> {};
428 template <typename T
>
429 struct is_trivially_move_assignable
: bool_constant
<__is_trivial(T
)> {};
437 #endif // MPARK_LIB_HPP