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
{
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 static constexpr bool value
= decltype(test
<T
>(0))::value
;
211 template <typename T
, bool = is_swappable
<T
>::value
>
212 struct is_nothrow_swappable
{
213 static constexpr bool value
=
214 noexcept(swap(std::declval
<T
&>(), std::declval
<T
&>()));
217 template <typename T
>
218 struct is_nothrow_swappable
<T
, false> : std::false_type
{};
220 } // namespace swappable
221 } // namespace detail
223 using detail::swappable::is_swappable
;
224 using detail::swappable::is_nothrow_swappable
;
228 #pragma warning(push)
229 #pragma warning(disable : 4100)
231 template <typename F
, typename
... As
>
232 inline constexpr auto invoke(F
&&f
, As
&&... as
)
233 RETURN(lib::forward
<F
>(f
)(lib::forward
<As
>(as
)...))
238 template <typename B
, typename T
, typename D
>
239 inline constexpr auto invoke(T
B::*pmv
, D
&&d
)
240 RETURN(lib::forward
<D
>(d
).*pmv
)
242 template <typename Pmv
, typename Ptr
>
243 inline constexpr auto invoke(Pmv pmv
, Ptr
&&ptr
)
244 RETURN((*lib::forward
<Ptr
>(ptr
)).*pmv
)
246 template <typename B
, typename T
, typename D
, typename
... As
>
247 inline constexpr auto invoke(T
B::*pmf
, D
&&d
, As
&&... as
)
248 RETURN((lib::forward
<D
>(d
).*pmf
)(lib::forward
<As
>(as
)...))
250 template <typename Pmf
, typename Ptr
, typename
... As
>
251 inline constexpr auto invoke(Pmf pmf
, Ptr
&&ptr
, As
&&... as
)
252 RETURN(((*lib::forward
<Ptr
>(ptr
)).*pmf
)(lib::forward
<As
>(as
)...))
256 template <typename Void
, typename
, typename
...>
257 struct invoke_result
{};
259 template <typename F
, typename
... Args
>
260 struct invoke_result
<void_t
<decltype(lib::invoke(
261 std::declval
<F
>(), std::declval
<Args
>()...))>,
265 lib::invoke(std::declval
<F
>(), std::declval
<Args
>()...))> {};
267 } // namespace detail
269 template <typename F
, typename
... Args
>
270 using invoke_result
= detail::invoke_result
<void, F
, Args
...>;
272 template <typename F
, typename
... Args
>
273 using invoke_result_t
= typename invoke_result
<F
, Args
...>::type
;
277 template <typename Void
, typename
, typename
...>
278 struct is_invocable
: std::false_type
{};
280 template <typename F
, typename
... Args
>
281 struct is_invocable
<void_t
<invoke_result_t
<F
, Args
...>>, F
, Args
...>
284 template <typename Void
, typename
, typename
, typename
...>
285 struct is_invocable_r
: std::false_type
{};
287 template <typename R
, typename F
, typename
... Args
>
288 struct is_invocable_r
<void_t
<invoke_result_t
<F
, Args
...>>,
292 : std::is_convertible
<invoke_result_t
<F
, Args
...>, R
> {};
294 } // namespace detail
296 template <typename F
, typename
... Args
>
297 using is_invocable
= detail::is_invocable
<void, F
, Args
...>;
299 template <typename R
, typename F
, typename
... Args
>
300 using is_invocable_r
= detail::is_invocable_r
<void, R
, F
, Args
...>;
303 #ifdef MPARK_BUILTIN_ADDRESSOF
304 template <typename T
>
305 inline constexpr T
*addressof(T
&arg
) {
306 return __builtin_addressof(arg
);
311 namespace has_addressof_impl
{
315 template <typename T
>
316 inline fail
operator&(T
&&);
318 template <typename T
>
319 inline static constexpr bool impl() {
320 return (std::is_class
<T
>::value
|| std::is_union
<T
>::value
) &&
321 !std::is_same
<decltype(&std::declval
<T
&>()), fail
>::value
;
324 } // namespace has_addressof_impl
326 template <typename T
>
327 using has_addressof
= bool_constant
<has_addressof_impl::impl
<T
>()>;
329 template <typename T
>
330 inline constexpr T
*addressof(T
&arg
, std::true_type
) {
331 return std::addressof(arg
);
334 template <typename T
>
335 inline constexpr T
*addressof(T
&arg
, std::false_type
) {
339 } // namespace detail
341 template <typename T
>
342 inline constexpr T
*addressof(T
&arg
) {
343 return detail::addressof(arg
, detail::has_addressof
<T
>{});
347 template <typename T
>
348 inline constexpr T
*addressof(const T
&&) = delete;
352 template <typename T
>
353 struct remove_all_extents
: identity
<T
> {};
355 template <typename T
, std::size_t N
>
356 struct remove_all_extents
<array
<T
, N
>> : remove_all_extents
<T
> {};
358 template <typename T
>
359 using remove_all_extents_t
= typename remove_all_extents
<T
>::type
;
361 template <std::size_t N
>
362 using size_constant
= std::integral_constant
<std::size_t, N
>;
364 template <std::size_t I
, typename T
>
365 struct indexed_type
: size_constant
<I
>, identity
<T
> {};
367 template <bool... Bs
>
368 using all
= std::is_same
<integer_sequence
<bool, true, Bs
...>,
369 integer_sequence
<bool, Bs
..., true>>;
371 #ifdef MPARK_TYPE_PACK_ELEMENT
372 template <std::size_t I
, typename
... Ts
>
373 using type_pack_element_t
= __type_pack_element
<I
, Ts
...>;
375 template <std::size_t I
, typename
... Ts
>
376 struct type_pack_element_impl
{
381 template <std::size_t... Is
>
382 struct set
<index_sequence
<Is
...>> : indexed_type
<Is
, Ts
>... {};
384 template <typename T
>
385 inline static std::enable_if
<true, T
> impl(indexed_type
<I
, T
>);
387 inline static std::enable_if
<false> impl(...);
390 using type
= decltype(impl(set
<index_sequence_for
<Ts
...>>{}));
393 template <std::size_t I
, typename
... Ts
>
394 using type_pack_element
= typename type_pack_element_impl
<I
, Ts
...>::type
;
396 template <std::size_t I
, typename
... Ts
>
397 using type_pack_element_t
= typename type_pack_element
<I
, Ts
...>::type
;
400 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
401 using std::is_trivially_copy_constructible
;
402 using std::is_trivially_move_constructible
;
403 using std::is_trivially_copy_assignable
;
404 using std::is_trivially_move_assignable
;
406 template <typename T
>
407 struct is_trivially_copy_constructible
409 std::is_copy_constructible
<T
>::value
&& __has_trivial_copy(T
)> {};
411 template <typename T
>
412 struct is_trivially_move_constructible
: bool_constant
<__is_trivial(T
)> {};
414 template <typename T
>
415 struct is_trivially_copy_assignable
417 std::is_copy_assignable
<T
>::value
&& __has_trivial_assign(T
)> {};
419 template <typename T
>
420 struct is_trivially_move_assignable
: bool_constant
<__is_trivial(T
)> {};
423 template <typename T
, bool>
424 struct dependent_type
: T
{};
426 template <typename Is
, std::size_t J
>
429 template <typename Is
, std::size_t J
>
430 using push_back_t
= typename push_back
<Is
, J
>::type
;
432 template <std::size_t... Is
, std::size_t J
>
433 struct push_back
<index_sequence
<Is
...>, J
> {
434 using type
= index_sequence
<Is
..., J
>;
442 #endif // MPARK_LIB_HPP