1fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/*
2fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Copyright (C) 2016 The Android Open Source Project
3fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
4fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * you may not use this file except in compliance with the License.
6fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * You may obtain a copy of the License at
7fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
8fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
10fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Unless required by applicable law or agreed to in writing, software
11fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * See the License for the specific language governing permissions and
14fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * limitations under the License.
15fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
16fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
17fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#ifndef STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
18fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#define STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
19fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
20fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#include <type_traits>
21fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
22fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarnamespace android {
23fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
24fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
25fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * std::is_signed, is_unsigned and is_integral does not consider enums even though the standard
26fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * considers them integral. Create modified versions of these here. Also create a wrapper around
27fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * std::underlying_type that does not require checking if the type is an enum.
28fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
29fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
30fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
31fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Type support utility class to check if a type is an integral type or an enum.
32fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
33fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T>
34fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct is_integral_or_enum
35fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    : std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value> { };
36fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
37fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
38fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Type support utility class to get the underlying std::is_integral supported type for a type.
39fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * This returns the underlying type for enums, and the same type for types covered by
40fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * std::is_integral.
41fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
42fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * This is also used as a conditional to return an alternate type if the template param is not
43fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * an integral or enum type (as in underlying_integral_type<T, TypeIfNotEnumOrIntegral>::type).
44fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
45fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T,
46fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        typename U=typename std::enable_if<is_integral_or_enum<T>::value>::type,
47fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        bool=std::is_enum<T>::value,
48fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        bool=std::is_integral<T>::value>
49fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct underlying_integral_type {
50fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!std::is_enum<T>::value, "T should not be enum here");
51fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!std::is_integral<T>::value, "T should not be integral here");
52fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef U type;
53fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
54fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
55fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/** Specialization for enums. */
56fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T, typename U>
57fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct underlying_integral_type<T, U, true, false> {
58fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(std::is_enum<T>::value, "T should be enum here");
59fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!std::is_integral<T>::value, "T should not be integral here");
60fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef typename std::underlying_type<T>::type type;
61fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
62fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
63fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/** Specialization for non-enum std-integral types. */
64fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T, typename U>
65fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct underlying_integral_type<T, U, false, true> {
66fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!std::is_enum<T>::value, "T should not be enum here");
67fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(std::is_integral<T>::value, "T should be integral here");
68fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef T type;
69fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
70fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
71fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
72fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Type support utility class to check if the underlying integral type is signed.
73fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
74fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T>
75fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct is_signed_integral
76fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    : std::integral_constant<bool, std::is_signed<
77fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            typename underlying_integral_type<T, unsigned>::type>::value> { };
78fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
79fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
80fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Type support utility class to check if the underlying integral type is unsigned.
81fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
82fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<typename T>
83fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct is_unsigned_integral
84fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    : std::integral_constant<bool, std::is_unsigned<
85fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            typename underlying_integral_type<T, signed>::type>::value> {
86fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
87fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
88e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
89e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type support relationship query template.
90e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
91e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * If T occurs as one of the types in Us with the same const-volatile qualifications, provides the
92e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * member constant |value| equal to true. Otherwise value is false.
93e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
94e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename ...Us>
95e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct is_one_of;
96e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
97e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \if 0
98e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
99e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when first type matches the searched type.
100e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
101e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename ...Us>
102e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct is_one_of<T, T, Us...> : std::true_type {};
103e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
104e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
105e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when first type does not match the searched type.
106e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
107e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename U, typename ...Us>
108e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct is_one_of<T, U, Us...> : is_one_of<T, Us...> {};
109e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
110e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
111e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are no types to search.
112e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
113e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T>
114e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct is_one_of<T> : std::false_type {};
115e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endif
116e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
117e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
118e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type support relationship query template.
119e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
120e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * If all types in Us are unique, provides the member constant |value| equal to true.
121e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Otherwise value is false.
122e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
123e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Us>
124e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct are_unique;
125e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
126e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \if 0
127e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
128e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are no types.
129e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
130e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<>
131e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct are_unique<> : std::true_type {};
132e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
133e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
134e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there is at least one type to check.
135e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
136e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename ...Us>
137e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct are_unique<T, Us...>
138e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    : std::integral_constant<bool, are_unique<Us...>::value && !is_one_of<T, Us...>::value> {};
139e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endif
140e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
141e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \if 0
142e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T, typename ...Us>
143e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_impl;
144e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
145e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
146e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are no types to search.
147e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
148e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T>
149e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_impl<Base, T> : std::integral_constant<size_t, 0> {};
150e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
151e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
152e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when T is the first type in Us.
153e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
154e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T, typename ...Us>
155e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_impl<Base, T, T, Us...> : std::integral_constant<size_t, Base> {};
156e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
157e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
158e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when T is not the first type in Us.
159e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
160e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T, typename U, typename ...Us>
161e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_impl<Base, T, U, Us...>
162e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    : std::integral_constant<size_t, _find_first_impl<Base + 1, T, Us...>::value> {};
163e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
164e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endif
165e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
166e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
167e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type support relationship query template.
168e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
169e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * If T occurs in Us, index is the 1-based left-most index of T in Us. Otherwise, index is 0.
170e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
171e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename ...Us>
172e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct find_first {
173e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static constexpr size_t index = _find_first_impl<1, T, Us...>::value;
174e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
175e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
176e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \if 0
177e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
178e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper class for find_first_convertible_to template.
179e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
180e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Adds a base index.
181e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
182e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T, typename ...Us>
183e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_convertible_to_helper;
184e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
185e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
186e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for when there are more types to consider
187e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
188e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T, typename U, typename ...Us>
189e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_convertible_to_helper<Base, T, U, Us...> {
190e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static constexpr size_t index =
191e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        std::is_convertible<T, U>::value ? Base :
192e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _find_first_convertible_to_helper<Base + 1, T, Us...>::index;
193e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    typedef typename std::conditional<
194e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        std::is_convertible<T, U>::value, U,
195e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typename _find_first_convertible_to_helper<Base + 1, T, Us...>::type>::type type;
196e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
197e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
198e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
199e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for when there are no more types to consider
200e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
201e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<size_t Base, typename T>
202e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct _find_first_convertible_to_helper<Base, T> {
203e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static constexpr size_t index = 0;
204e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    typedef void type;
205e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
206e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
207e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endif
208e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
209e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
210e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type support template that returns the type that T can be implicitly converted into, and its
211e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * index, from a list of other types (Us).
212e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
213e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Returns index of 0 and type of void if there are no convertible types.
214e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
215e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type that is converted
216e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Us types into which the conversion is considered
217e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
218e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T, typename ...Us>
219e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct find_first_convertible_to : public _find_first_convertible_to_helper<1, T, Us...> { };
220e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
221fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar}  // namespace android
222fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
223fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#endif  // STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
224fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
225