• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Copyright 2019 The Fuchsia Authors. All rights reserved.
16 // Use of this source code is governed by a BSD-style license that can be
17 // found in the LICENSE file.
18 
19 #pragma once
20 
21 #include <type_traits>
22 #include <utility>
23 
24 namespace gfxstream::guest {
25 namespace fit {
26 namespace internal {
27 
28 // Utility to return the first type in a parameter pack.
29 template <typename... Ts>
30 struct First;
31 template <typename FirstType, typename... Rest>
32 struct First<FirstType, Rest...> {
33     using Type = FirstType;
34 };
35 
36 template <typename... Ts>
37 using First_t = typename First<Ts...>::Type;
38 
39 // Utility to count the occurences of type T in the parameter pack Ts.
40 template <typename T, typename... Ts>
41 struct OccurencesOf : std::integral_constant<size_t, 0> {};
42 template <typename T, typename U>
43 struct OccurencesOf<T, U> : std::integral_constant<size_t, std::is_same<T, U>::value> {};
44 template <typename T, typename First, typename... Rest>
45 struct OccurencesOf<T, First, Rest...>
46     : std::integral_constant<size_t,
47                              OccurencesOf<T, First>::value + OccurencesOf<T, Rest...>::value> {};
48 
49 template <typename T, typename... Ts>
50 constexpr size_t occurencesOf = OccurencesOf<T, Ts...>::value;
51 
52 // Utility to remove const, volatile, and reference qualifiers.
53 template <typename T>
54 using RemoveCvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
55 
56 // Evaluates to truth-like when type T matches type U with cv-reference removed.
57 template <typename T, typename U>
58 using NotSameType = std::negation<std::is_same<T, RemoveCvref_t<U>>>;
59 
60 // Concept helper for constructors.
61 template <typename... Conditions>
62 using RequiresConditions = std::enable_if_t<std::conjunction_v<Conditions...>, bool>;
63 
64 // Concept helper for assignment operators.
65 template <typename Return, typename... Conditions>
66 using AssignmentRequiresConditions =
67     std::enable_if_t<std::conjunction_v<Conditions...>, std::add_lvalue_reference_t<Return>>;
68 
69 // Evaluates to true when every element type of Ts is trivially destructible.
70 template <typename... Ts>
71 constexpr bool isTriviallyDestructible = std::conjunction_v<std::is_trivially_destructible<Ts>...>;
72 
73 // Evaluates to true when every element type of Ts is trivially copyable.
74 template <typename... Ts>
75 constexpr bool isTriviallyCopyable =
76     (std::conjunction_v<std::is_trivially_copy_assignable<Ts>...> &&
77      std::conjunction_v<std::is_trivially_copy_constructible<Ts>...>);
78 
79 // Evaluates to true when every element type of Ts is trivially movable.
80 template <typename... Ts>
81 constexpr bool isTriviallyMovable =
82     (std::conjunction_v<std::is_trivially_move_assignable<Ts>...> &&
83      std::conjunction_v<std::is_trivially_move_constructible<Ts>...>);
84 
85 // Enable if relational operator is convertible to bool and the optional
86 // conditions are true.
87 template <typename Op, typename... Conditions>
88 using enable_relop_t =
89     std::enable_if_t<(std::is_convertible<Op, bool>::value && std::conjunction_v<Conditions...>),
90                      bool>;
91 
92 template <typename T>
93 struct Identity {
94     using Type = T;
95 };
96 
97 // Evaluates to true when T is an unbounded array.
98 template <typename T>
99 struct IsUnboundedArray : std::conjunction<std::is_array<T>, std::negation<std::extent<T>>> {};
100 
101 // Returns true when T is a complete type or an unbounded array.
102 template <typename T, size_t = sizeof(T)>
103 constexpr bool isCompleteOrUnboundedArray(Identity<T>) {
104     return true;
105 }
106 template <typename Identity, typename T = typename Identity::Type>
107 constexpr bool isCompleteOrUnboundedArray(Identity) {
108     return std::disjunction<std::is_reference<T>, std::is_function<T>, std::is_void<T>,
109                             IsUnboundedArray<T>>::value;
110 }
111 
112 // Using swap for ADL. This directive is contained within the fit::internal
113 // namespace, which prevents leaking std::swap into user namespaces. Doing this
114 // at namespace scope is necessary to lookup swap via ADL while preserving the
115 // noexcept() specification of the resulting lookup.
116 using std::swap;
117 
118 // Evaluates to true when T is swappable.
119 template <typename T, typename = void>
120 struct IsSwappable : std::false_type {
121     static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
122                   "T must be a complete type or an unbounded array!");
123 };
124 template <typename T>
125 struct IsSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
126     : std::true_type {
127     static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
128                   "T must be a complete type or an unbounded array!");
129 };
130 
131 // Evaluates to true when T is nothrow swappable.
132 template <typename T, typename = void>
133 struct IsNothrowSwappable : std::false_type {
134     static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
135                   "T must be a complete type or an unbounded array!");
136 };
137 template <typename T>
138 struct IsNothrowSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
139     : std::integral_constant<bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))> {
140     static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
141                   "T must be a complete type or an unbounded array!");
142 };
143 
144 }  // namespace internal
145 }  // namespace fit
146 }  // namespace gfxstream::guest
147