diff options
Diffstat (limited to 'third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h')
-rw-r--r-- | third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h new file mode 100644 index 000000000..a5da381ae --- /dev/null +++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h @@ -0,0 +1,137 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_ +#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_ + +#include <cstddef> +#include <utility> + +#include "../type_traits.h" + +namespace cpp17 { +namespace internal { + +template <typename Tag> +struct instantiate_templated_tag { + static constexpr const Tag storage{}; +}; + +template <typename Tag> +constexpr const Tag instantiate_templated_tag<Tag>::storage; + +template <typename T, typename ValueType, ValueType Value> +struct inline_storage { + static constexpr const ValueType storage{Value}; +}; + +template <typename T, typename ValueType, ValueType Value> +constexpr const ValueType inline_storage<T, ValueType, Value>::storage; + +// Utility to return the first type in a parameter pack. +template <typename... Ts> +struct first; +template <typename First, typename... Rest> +struct first<First, Rest...> { + using type = First; +}; + +template <typename... Ts> +using first_t = typename first<Ts...>::type; + +// Utility to count the occurences of type T in the parameter pack Ts. +template <typename T, typename... Ts> +struct occurences_of : std::integral_constant<std::size_t, 0> {}; +template <typename T, typename U> +struct occurences_of<T, U> : std::integral_constant<std::size_t, std::is_same<T, U>::value> {}; +template <typename T, typename First, typename... Rest> +struct occurences_of<T, First, Rest...> + : std::integral_constant<std::size_t, + occurences_of<T, First>::value + occurences_of<T, Rest...>::value> {}; + +template <typename T, typename... Ts> +constexpr std::size_t occurences_of_v = occurences_of<T, Ts...>::value; + +// Evaluates to truth-like when type T matches type U with cv-reference removed. +template <typename T, typename U> +using not_same_type = negation<std::is_same<T, ::cpp20::remove_cvref_t<U>>>; + +// Concept helper for constructors. +template <typename... Conditions> +using requires_conditions = std::enable_if_t<conjunction_v<Conditions...>, bool>; + +// Concept helper for assignment operators. +template <typename Return, typename... Conditions> +using assignment_requires_conditions = + std::enable_if_t<conjunction_v<Conditions...>, std::add_lvalue_reference_t<Return>>; + +// Evaluates to true when every element type of Ts is trivially destructible. +template <typename... Ts> +constexpr bool is_trivially_destructible_v = conjunction_v<std::is_trivially_destructible<Ts>...>; + +// Evaluates to true when every element type of Ts is trivially copyable. +template <typename... Ts> +constexpr bool is_trivially_copyable_v = + (conjunction_v<std::is_trivially_copy_assignable<Ts>...> && + conjunction_v<std::is_trivially_copy_constructible<Ts>...>); + +// Evaluates to true when every element type of Ts is trivially movable. +template <typename... Ts> +constexpr bool is_trivially_movable_v = + (conjunction_v<std::is_trivially_move_assignable<Ts>...> && + conjunction_v<std::is_trivially_move_constructible<Ts>...>); + +// Enable if relational operator is convertible to bool and the optional +// conditions are true. +template <typename Op, typename... Conditions> +using enable_relop_t = + std::enable_if_t<(std::is_convertible<Op, bool>::value && conjunction_v<Conditions...>), bool>; + +// Returns true when T is a complete type or an unbounded array. +template <typename T, std::size_t = sizeof(T)> +constexpr bool is_complete_or_unbounded_array(::cpp20::type_identity<T>) { + return true; +} +template <typename Identity, typename T = typename Identity::type> +constexpr bool is_complete_or_unbounded_array(Identity) { + return disjunction<std::is_reference<T>, std::is_function<T>, std::is_void<T>, + ::cpp20::is_unbounded_array<T>>::value; +} + +// Using swap for ADL. This directive is contained within the cpp17::internal +// namespace, which prevents leaking std::swap into user namespaces. Doing this +// at namespace scope is necessary to lookup swap via ADL while preserving the +// noexcept() specification of the resulting lookup. +using std::swap; + +// Evaluates to true when T is swappable. +template <typename T, typename = void> +struct is_swappable : std::false_type { + static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}), + "T must be a complete type or an unbounded array!"); +}; +template <typename T> +struct is_swappable<T, void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>> + : std::true_type { + static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}), + "T must be a complete type or an unbounded array!"); +}; + +// Evaluates to true when T is nothrow swappable. +template <typename T, typename = void> +struct is_nothrow_swappable : std::false_type { + static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}), + "T must be a complete type or an unbounded array!"); +}; +template <typename T> +struct is_nothrow_swappable<T, void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>> + : std::integral_constant<bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))> { + static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}), + "T must be a complete type or an unbounded array!"); +}; + +} // namespace internal +} // namespace cpp17 + +#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_ |