1 #ifndef ANDROID_PDX_RPC_ENUMERATION_H_
2 #define ANDROID_PDX_RPC_ENUMERATION_H_
3 
4 #include <pdx/rpc/sequence.h>
5 
6 namespace android {
7 namespace pdx {
8 namespace rpc {
9 
10 // Utility for manipulating lists of types. Provides operations to lookup an
11 // element by type or index.
12 
13 namespace detail {
14 
15 // Helper type that captures type and index for each element of a type
16 // enumeration.
17 template <std::size_t I, typename T>
18 struct IndexedElement {
19   using Type = T;
20   static constexpr std::size_t Index = I;
21 };
22 
23 // Helper type that captures an IndexSequence and corresponding list of types.
24 template <typename Is, typename... Ts>
25 struct ElementIndexer;
26 
27 // Partial specialization that generates an instantiation of IndexElement<I, T>
28 // for each element of a type enumeration using inheritance. Once a type
29 // enumeration is instantiated this way the compiler is able to deduce either I
30 // or T from the other using the method below.
31 template <std::size_t... Is, typename... Ts>
32 struct ElementIndexer<IndexSequence<Is...>, Ts...> : IndexedElement<Is, Ts>... {
33 };
34 
35 // Helper function that causes the compiler to deduce an IndexedElement<I, T>
36 // given T.
37 template <typename T, std::size_t I>
38 static IndexedElement<I, T> SelectElementByType(IndexedElement<I, T>);
39 
40 // Helper function that causes the compiler to deduce an IndexedElement<I, T>
41 // given I.
42 template <std::size_t I, typename T>
43 static IndexedElement<I, T> SelectElementByIndex(IndexedElement<I, T>);
44 
45 }  // namespace detail
46 
47 // Deduces the IndexedElement<I, T> given T and a type sequence Ts. This may be
48 // used to determine the index of T within Ts at compile time.
49 template <typename T, typename... Ts>
50 using ElementForType = decltype(detail::SelectElementByType<T>(
51     detail::ElementIndexer<typename IndexSequenceFor<Ts...>::type, Ts...>{}));
52 
53 // Deduces the IndexedElement<I, T> given I and a type sequence Ts. This may be
54 // used to determine the type of the element at index I within Ts at compile
55 // time. Tuple operations may also be used to accomplish the same task, however
56 // this implementation is provided here for symmetry.
57 template <std::size_t I, typename... Ts>
58 using ElementForIndex = decltype(detail::SelectElementByIndex<I>(
59     detail::ElementIndexer<typename IndexSequenceFor<Ts...>::type, Ts...>{}));
60 
61 }  // namespace rpc
62 }  // namespace pdx
63 }  // namespace android
64 
65 #endif  // ANDROID_PDX_RPC_ENUMERATION_H_
66