1#ifndef ANDROID_PDX_RPC_VARIANT_H_
2#define ANDROID_PDX_RPC_VARIANT_H_
3
4#include <cstdint>
5#include <tuple>
6#include <type_traits>
7
8namespace android {
9namespace pdx {
10namespace rpc {
11
12// Type tag denoting an empty variant.
13struct EmptyVariant {};
14
15namespace detail {
16
17// Type for matching tagged overloads.
18template <typename T>
19struct TypeTag {};
20
21// Determines the type of the I-th element of Types....
22template <std::size_t I, typename... Types>
23using TypeForIndex = std::tuple_element_t<I, std::tuple<Types...>>;
24
25// Determines the type tag for the I-th element of Types....
26template <std::size_t I, typename... Types>
27using TypeTagForIndex = TypeTag<TypeForIndex<I, Types...>>;
28
29// Enable if T(Args...) is well formed.
30template <typename R, typename T, typename... Args>
31using EnableIfConstructible =
32    typename std::enable_if<std::is_constructible<T, Args...>::value, R>::type;
33// Enable if T(Args...) is not well formed.
34template <typename R, typename T, typename... Args>
35using EnableIfNotConstructible =
36    typename std::enable_if<!std::is_constructible<T, Args...>::value, R>::type;
37
38// Determines whether T is an element of Types...;
39template <typename... Types>
40struct HasType : std::false_type {};
41template <typename T, typename U>
42struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
43template <typename T, typename First, typename... Rest>
44struct HasType<T, First, Rest...>
45    : std::integral_constant<bool, HasType<T, First>::value ||
46                                       HasType<T, Rest...>::value> {};
47
48// Defines set operations on a set of Types...
49template <typename... Types>
50struct Set {
51  // Default specialization catches the empty set, which is always a subset.
52  template <typename...>
53  struct IsSubset : std::true_type {};
54  template <typename T>
55  struct IsSubset<T> : HasType<T, Types...> {};
56  template <typename First, typename... Rest>
57  struct IsSubset<First, Rest...>
58      : std::integral_constant<bool, IsSubset<First>::value &&
59                                         IsSubset<Rest...>::value> {};
60};
61
62// Determines the number of elements of Types... that are constructible from
63// From.
64template <typename... Types>
65struct ConstructibleCount;
66template <typename From, typename To>
67struct ConstructibleCount<From, To>
68    : std::integral_constant<std::size_t,
69                             std::is_constructible<To, From>::value> {};
70template <typename From, typename First, typename... Rest>
71struct ConstructibleCount<From, First, Rest...>
72    : std::integral_constant<std::size_t,
73                             std::is_constructible<First, From>::value +
74                                 ConstructibleCount<From, Rest...>::value> {};
75
76// Enable if T is an element of Types...
77template <typename R, typename T, typename... Types>
78using EnableIfElement =
79    typename std::enable_if<HasType<T, Types...>::value, R>::type;
80// Enable if T is not an element of Types...
81template <typename R, typename T, typename... Types>
82using EnableIfNotElement =
83    typename std::enable_if<!HasType<T, Types...>::value, R>::type;
84
85// Enable if T is convertible to an element of Types... T is considered
86// convertible IIF a single element of Types... is assignable from T and T is
87// not a direct element of Types...
88template <typename R, typename T, typename... Types>
89using EnableIfConvertible =
90    typename std::enable_if<!HasType<T, Types...>::value &&
91                                ConstructibleCount<T, Types...>::value == 1,
92                            R>::type;
93
94// Enable if T is assignable to an element of Types... T is considered
95// assignable IFF a single element of Types... is constructible from T or T is a
96// direct element of Types.... Note that T is REQUIRED to be an element of
97// Types... when multiple elements are constructible from T to prevent ambiguity
98// in conversion.
99template <typename R, typename T, typename... Types>
100using EnableIfAssignable =
101    typename std::enable_if<HasType<T, Types...>::value ||
102                                ConstructibleCount<T, Types...>::value == 1,
103                            R>::type;
104
105// Selects a type for SFINAE constructor selection.
106template <bool CondA, typename SelectA, typename SelectB>
107using Select = std::conditional_t<CondA, SelectA, SelectB>;
108
109// Recursive union type.
110template <typename... Types>
111union Union;
112
113// Specialization handling a singular type, terminating template recursion.
114template <typename Type>
115union Union<Type> {
116  Union() {}
117  ~Union() {}
118
119  template <typename T>
120  Union(std::int32_t index, std::int32_t* index_out, TypeTag<Type>, T&& value)
121      : first_(std::forward<T>(value)) {
122    *index_out = index;
123  }
124  template <typename T, typename = EnableIfAssignable<void, T, Type>>
125  Union(std::int32_t index, std::int32_t* index_out, T&& value)
126      : first_(std::forward<T>(value)) {
127    *index_out = index;
128  }
129
130  Type& get(TypeTag<Type>) { return first_; }
131  const Type& get(TypeTag<Type>) const { return first_; }
132  EmptyVariant get(TypeTag<EmptyVariant>) const { return {}; }
133  constexpr std::int32_t index(TypeTag<Type>) const { return 0; }
134
135  template <typename... Args>
136  std::int32_t Construct(TypeTag<Type>, Args&&... args) {
137    new (&first_) Type(std::forward<Args>(args)...);
138    return 0;
139  }
140  template <typename... Args>
141  EnableIfConstructible<std::int32_t, Type, Args...> Construct(Args&&... args) {
142    new (&first_) Type(std::forward<Args>(args)...);
143    return 0;
144  }
145
146  void Destruct(std::int32_t target_index) {
147    if (target_index == index(TypeTag<Type>{})) {
148      (&get(TypeTag<Type>{}))->~Type();
149    }
150  }
151
152  template <typename T>
153  bool Assign(TypeTag<Type>, std::int32_t target_index, T&& value) {
154    if (target_index == 0) {
155      first_ = std::forward<T>(value);
156      return true;
157    } else {
158      return false;
159    }
160  }
161  template <typename T>
162  EnableIfConstructible<bool, Type, T> Assign(std::int32_t target_index,
163                                              T&& value) {
164    if (target_index == 0) {
165      first_ = std::forward<T>(value);
166      return true;
167    } else {
168      return false;
169    }
170  }
171  template <typename T>
172  EnableIfNotConstructible<bool, Type, T> Assign(std::int32_t /*target_index*/,
173                                                 T&& /*value*/) {
174    return false;
175  }
176
177  template <typename Op>
178  decltype(auto) Visit(std::int32_t target_index, Op&& op) {
179    if (target_index == index(TypeTag<Type>{}))
180      return std::forward<Op>(op)(get(TypeTag<Type>{}));
181    else
182      return std::forward<Op>(op)(get(TypeTag<EmptyVariant>{}));
183  }
184  template <typename Op>
185  decltype(auto) Visit(std::int32_t target_index, Op&& op) const {
186    if (target_index == index(TypeTag<Type>{}))
187      return std::forward<Op>(op)(get(TypeTag<Type>{}));
188    else
189      return std::forward<Op>(op)(get(TypeTag<EmptyVariant>{}));
190  }
191
192  template <typename... Args>
193  bool Become(std::int32_t target_index, Args&&... args) {
194    if (target_index == index(TypeTag<Type>{})) {
195      Construct(TypeTag<Type>{}, std::forward<Args>(args)...);
196      return true;
197    } else {
198      return false;
199    }
200  }
201
202 private:
203  Type first_;
204};
205
206// Specialization that recursively unions types from the paramater pack.
207template <typename First, typename... Rest>
208union Union<First, Rest...> {
209  Union() {}
210  ~Union() {}
211
212  template <typename T>
213  Union(std::int32_t index, std::int32_t* index_out, TypeTag<First>, T&& value)
214      : first_(std::forward<T>(value)) {
215    *index_out = index;
216  }
217  template <typename T, typename U>
218  Union(std::int32_t index, std::int32_t* index_out, TypeTag<T>, U&& value)
219      : rest_(index + 1, index_out, TypeTag<T>{}, std::forward<U>(value)) {}
220
221  struct FirstType {};
222  struct RestType {};
223  template <typename T>
224  using SelectConstructor =
225      Select<ConstructibleCount<T, First>::value == 1, FirstType, RestType>;
226
227  template <typename T>
228  Union(std::int32_t index, std::int32_t* index_out, T&& value)
229      : Union(index, index_out, std::forward<T>(value),
230              SelectConstructor<T>{}) {}
231
232  template <typename T>
233  Union(std::int32_t index, std::int32_t* index_out, T&& value, FirstType)
234      : first_(std::forward<T>(value)) {
235    *index_out = index;
236  }
237  template <typename T>
238  Union(std::int32_t index, std::int32_t* index_out, T&& value, RestType)
239      : rest_(index + 1, index_out, std::forward<T>(value)) {}
240
241  First& get(TypeTag<First>) { return first_; }
242  const First& get(TypeTag<First>) const { return first_; }
243  constexpr std::int32_t index(TypeTag<First>) const { return 0; }
244
245  template <typename T>
246  T& get(TypeTag<T>) {
247    return rest_.template get(TypeTag<T>{});
248  }
249  template <typename T>
250  const T& get(TypeTag<T>) const {
251    return rest_.template get(TypeTag<T>{});
252  }
253  template <typename T>
254  constexpr std::int32_t index(TypeTag<T>) const {
255    return 1 + rest_.template index(TypeTag<T>{});
256  }
257
258  template <typename... Args>
259  std::int32_t Construct(TypeTag<First>, Args&&... args) {
260    new (&first_) First(std::forward<Args>(args)...);
261    return 0;
262  }
263  template <typename T, typename... Args>
264  std::int32_t Construct(TypeTag<T>, Args&&... args) {
265    return 1 +
266           rest_.template Construct(TypeTag<T>{}, std::forward<Args>(args)...);
267  }
268
269  template <typename... Args>
270  EnableIfConstructible<std::int32_t, First, Args...> Construct(
271      Args&&... args) {
272    new (&first_) First(std::forward<Args>(args)...);
273    return 0;
274  }
275  template <typename... Args>
276  EnableIfNotConstructible<std::int32_t, First, Args...> Construct(
277      Args&&... args) {
278    return 1 + rest_.template Construct(std::forward<Args>(args)...);
279  }
280
281  void Destruct(std::int32_t target_index) {
282    if (target_index == index(TypeTag<First>{})) {
283      (get(TypeTag<First>{})).~First();
284    } else {
285      rest_.Destruct(target_index - 1);
286    }
287  }
288
289  template <typename T>
290  bool Assign(TypeTag<First>, std::int32_t target_index, T&& value) {
291    if (target_index == 0) {
292      first_ = std::forward<T>(value);
293      return true;
294    } else {
295      return false;
296    }
297  }
298  template <typename T, typename U>
299  bool Assign(TypeTag<T>, std::int32_t target_index, U&& value) {
300    return rest_.Assign(TypeTag<T>{}, target_index - 1, std::forward<U>(value));
301  }
302  template <typename T>
303  EnableIfConstructible<bool, First, T> Assign(std::int32_t target_index,
304                                               T&& value) {
305    if (target_index == 0) {
306      first_ = std::forward<T>(value);
307      return true;
308    } else {
309      return rest_.Assign(target_index - 1, std::forward<T>(value));
310    }
311  }
312  template <typename T>
313  EnableIfNotConstructible<bool, First, T> Assign(std::int32_t target_index,
314                                                  T&& value) {
315    return rest_.Assign(target_index - 1, std::forward<T>(value));
316  }
317
318  // Recursively traverses the union and calls Op on the active value when the
319  // active type is found. If the union is empty Op is called on EmptyVariant.
320  // TODO(eieio): This could be refactored into an array or jump table. It's
321  // unclear whether this would be more efficient for practical variant arity.
322  template <typename Op>
323  decltype(auto) Visit(std::int32_t target_index, Op&& op) {
324    if (target_index == index(TypeTag<First>{}))
325      return std::forward<Op>(op)(get(TypeTag<First>{}));
326    else
327      return rest_.Visit(target_index - 1, std::forward<Op>(op));
328  }
329  template <typename Op>
330  decltype(auto) Visit(std::int32_t target_index, Op&& op) const {
331    if (target_index == index(TypeTag<First>{}))
332      return std::forward<Op>(op)(get(TypeTag<First>{}));
333    else
334      return rest_.Visit(target_index - 1, std::forward<Op>(op));
335  }
336
337  template <typename... Args>
338  bool Become(std::int32_t target_index, Args&&... args) {
339    if (target_index == index(TypeTag<First>{})) {
340      Construct(TypeTag<First>{}, std::forward<Args>(args)...);
341      return true;
342    } else {
343      return rest_.Become(target_index - 1, std::forward<Args>(args)...);
344    }
345  }
346
347 private:
348  First first_;
349  Union<Rest...> rest_;
350};
351
352}  // namespace detail
353
354template <typename... Types>
355class Variant {
356 private:
357  // Convenience types.
358  template <typename T>
359  using TypeTag = detail::TypeTag<T>;
360  template <typename T>
361  using DecayedTypeTag = TypeTag<std::decay_t<T>>;
362  template <std::size_t I>
363  using TypeForIndex = detail::TypeForIndex<I, Types...>;
364  template <std::size_t I>
365  using TypeTagForIndex = detail::TypeTagForIndex<I, Types...>;
366  template <typename T>
367  using HasType = detail::HasType<T, Types...>;
368  template <typename R, typename T>
369  using EnableIfElement = detail::EnableIfElement<R, T, Types...>;
370  template <typename R, typename T>
371  using EnableIfConvertible = detail::EnableIfConvertible<R, T, Types...>;
372  template <typename R, typename T>
373  using EnableIfAssignable = detail::EnableIfAssignable<R, T, Types...>;
374
375  struct Direct {};
376  struct Convert {};
377  template <typename T>
378  using SelectConstructor = detail::Select<HasType<T>::value, Direct, Convert>;
379
380  // Constructs by type tag when T is an direct element of Types...
381  template <typename T>
382  explicit Variant(T&& value, Direct)
383      : value_(0, &index_, DecayedTypeTag<T>{}, std::forward<T>(value)) {}
384  // Conversion constructor when T is not a direct element of Types...
385  template <typename T>
386  explicit Variant(T&& value, Convert)
387      : value_(0, &index_, std::forward<T>(value)) {}
388
389 public:
390  // Variants are default construcible, regardless of whether the elements are
391  // default constructible. Default consruction yields an empty Variant.
392  Variant() {}
393  explicit Variant(EmptyVariant) {}
394  ~Variant() { Destruct(); }
395
396  // Copy and move construction from Variant types. Each element of OtherTypes
397  // must be convertible to an element of Types.
398  template <typename... OtherTypes>
399  explicit Variant(const Variant<OtherTypes...>& other) {
400    other.Visit([this](const auto& value) { Construct(value); });
401  }
402  template <typename... OtherTypes>
403  explicit Variant(Variant<OtherTypes...>&& other) {
404    other.Visit([this](auto&& value) { Construct(std::move(value)); });
405  }
406
407  // Construction from non-Variant types.
408  template <typename T, typename = EnableIfAssignable<void, T>>
409  explicit Variant(T&& value)
410      : Variant(std::forward<T>(value), SelectConstructor<T>{}) {}
411
412  // Performs assignment from type T belonging to Types. This overload takes
413  // priority to prevent implicit conversion in cases where T is implicitly
414  // convertible to multiple elements of Types.
415  template <typename T>
416  EnableIfElement<Variant&, T> operator=(T&& value) {
417    Assign(DecayedTypeTag<T>{}, std::forward<T>(value));
418    return *this;
419  }
420
421  // Performs assignment from type T not belonging to Types. This overload
422  // matches in cases where conversion is the only viable option.
423  template <typename T>
424  EnableIfConvertible<Variant&, T> operator=(T&& value) {
425    Assign(std::forward<T>(value));
426    return *this;
427  }
428
429  // Handles assignment from the empty type. This overload supports assignment
430  // in visitors using generic lambdas.
431  Variant& operator=(EmptyVariant) {
432    Assign(EmptyVariant{});
433    return *this;
434  }
435
436  // Assignment from Variant types. Each element of OtherTypes must be
437  // convertible to an element of Types. Forwards through non-Variant assignment
438  // operators to apply conversion checks.
439  template <typename... OtherTypes>
440  Variant& operator=(const Variant<OtherTypes...>& other) {
441    other.Visit([this](const auto& value) { *this = value; });
442    return *this;
443  }
444  template <typename... OtherTypes>
445  Variant& operator=(Variant<OtherTypes...>&& other) {
446    other.Visit([this](auto&& value) { *this = std::move(value); });
447    return *this;
448  }
449
450  // Becomes the target type, constructing a new element from the given
451  // arguments if necessary. No action is taken if the active element is already
452  // the target type. Otherwise the active element is destroyed and replaced by
453  // constructing an element of the new type using |Args|. An invalid target
454  // type index results in an empty Variant.
455  template <typename... Args>
456  void Become(std::int32_t target_index, Args&&... args) {
457    if (target_index != index()) {
458      Destruct();
459      index_ = value_.Become(target_index, std::forward<Args>(args)...)
460                   ? target_index
461                   : kEmptyIndex;
462    }
463  }
464
465  // Invokes |Op| on the active element. If the Variant is empty |Op| is invoked
466  // on EmptyVariant.
467  template <typename Op>
468  decltype(auto) Visit(Op&& op) {
469    return value_.Visit(index_, std::forward<Op>(op));
470  }
471  template <typename Op>
472  decltype(auto) Visit(Op&& op) const {
473    return value_.Visit(index_, std::forward<Op>(op));
474  }
475
476  // Index returned when the Variant is empty.
477  enum : std::int32_t { kEmptyIndex = -1 };
478
479  // Returns the index of the given type.
480  template <typename T>
481  constexpr std::int32_t index_of() const {
482    static_assert(HasType<T>::value, "T is not an element type of Variant.");
483    return value_.template index(DecayedTypeTag<T>{});
484  }
485
486  // Returns the index of the active type. If the Variant is empty -1 is
487  // returned.
488  std::int32_t index() const { return index_; }
489
490  // Returns true if the given type is active, false otherwise.
491  template <typename T>
492  bool is() const {
493    static_assert(HasType<T>::value, "T is not an element type of Variant.");
494    return index() == index_of<T>();
495  }
496
497  // Returns true if the Variant is empty, false otherwise.
498  bool empty() const { return index() == kEmptyIndex; }
499
500  // Element accessors. Returns a pointer to the active value if the given
501  // type/index is active, otherwise nullptr is returned.
502  template <typename T>
503  T* get() {
504    if (is<T>())
505      return &value_.template get(DecayedTypeTag<T>{});
506    else
507      return nullptr;
508  }
509  template <typename T>
510  const T* get() const {
511    if (is<T>())
512      return &value_.template get(DecayedTypeTag<T>{});
513    else
514      return nullptr;
515  }
516  template <std::size_t I>
517  TypeForIndex<I>* get() {
518    if (is<TypeForIndex<I>>())
519      return &value_.template get(TypeTagForIndex<I>{});
520    else
521      return nullptr;
522  }
523  template <std::size_t I>
524  const TypeForIndex<I>* get() const {
525    if (is<TypeForIndex<I>>())
526      return &value_.template get(TypeTagForIndex<I>{});
527    else
528      return nullptr;
529  }
530
531 private:
532  std::int32_t index_ = kEmptyIndex;
533  detail::Union<std::decay_t<Types>...> value_;
534
535  // Constructs an element from the given arguments and sets the Variant to the
536  // resulting type.
537  template <typename... Args>
538  void Construct(Args&&... args) {
539    index_ = value_.template Construct(std::forward<Args>(args)...);
540  }
541  void Construct(EmptyVariant) {}
542
543  // Destroys the active element of the Variant.
544  void Destruct() { value_.Destruct(index_); }
545
546  // Assigns the Variant when non-empty and the current type matches the target
547  // type, otherwise destroys the current value and constructs a element of the
548  // new type. Tagged assignment is used when T is an element of the Variant to
549  // prevent implicit conversion in cases where T is implicitly convertible to
550  // multiple element types.
551  template <typename T, typename U>
552  void Assign(TypeTag<T>, U&& value) {
553    if (!value_.template Assign(TypeTag<T>{}, index_, std::forward<U>(value))) {
554      Destruct();
555      Construct(TypeTag<T>{}, std::forward<U>(value));
556    }
557  }
558  template <typename T>
559  void Assign(T&& value) {
560    if (!value_.template Assign(index_, std::forward<T>(value))) {
561      Destruct();
562      Construct(std::forward<T>(value));
563    }
564  }
565  // Handles assignment from an empty Variant.
566  void Assign(EmptyVariant) { Destruct(); }
567};
568
569// Utility type to extract/convert values from a variant. This class simplifies
570// conditional logic to get/move/swap/action values from a variant when one or
571// more elements are compatible with the destination type.
572//
573// Example:
574//    Variant<int, bool, std::string> v(10);
575//    bool bool_value;
576//    if (IfAnyOf<int, bool>::Get(v, &bool_value)) {
577//      DoSomething(bool_value);
578//    } else {
579//      HandleInvalidType();
580//    }
581//    IfAnyOf<int>::Call(v, [](const auto& value) { DoSomething(value); });
582//
583template <typename... ValidTypes>
584struct IfAnyOf {
585  // Calls Op on the underlying value of the variant and returns true when the
586  // variant is a valid type, otherwise does nothing and returns false.
587  template <typename Op, typename... Types>
588  static bool Call(Variant<Types...>* variant, Op&& op) {
589    static_assert(
590        detail::Set<Types...>::template IsSubset<ValidTypes...>::value,
591        "ValidTypes may only contain element types from the Variant.");
592    return variant->Visit(CallOp<Op>{std::forward<Op>(op)});
593  }
594  template <typename Op, typename... Types>
595  static bool Call(const Variant<Types...>* variant, Op&& op) {
596    static_assert(
597        detail::Set<Types...>::template IsSubset<ValidTypes...>::value,
598        "ValidTypes may only contain element types from the Variant.");
599    return variant->Visit(CallOp<Op>{std::forward<Op>(op)});
600  }
601
602  // Gets/converts the underlying value of the variant to type T and returns
603  // true when the variant is a valid type, otherwise does nothing and returns
604  // false.
605  template <typename T, typename... Types>
606  static bool Get(const Variant<Types...>* variant, T* value_out) {
607    return Call(variant,
608                [value_out](const auto& value) { *value_out = value; });
609  }
610
611  // Moves the underlying value of the variant and returns true when the variant
612  // is a valid type, otherwise does nothing and returns false.
613  template <typename T, typename... Types>
614  static bool Take(Variant<Types...>* variant, T* value_out) {
615    return Call(variant,
616                [value_out](auto&& value) { *value_out = std::move(value); });
617  }
618
619  // Swaps the underlying value of the variant with |*value_out| and returns
620  // true when the variant is a valid type, otherwise does nothing and returns
621  // false.
622  template <typename T, typename... Types>
623  static bool Swap(Variant<Types...>* variant, T* value_out) {
624    return Call(variant,
625                [value_out](auto&& value) { std::swap(*value_out, value); });
626  }
627
628 private:
629  template <typename Op>
630  struct CallOp {
631    Op&& op;
632    template <typename U>
633    detail::EnableIfNotElement<bool, U, ValidTypes...> operator()(U&&) {
634      return false;
635    }
636    template <typename U>
637    detail::EnableIfElement<bool, U, ValidTypes...> operator()(const U& value) {
638      std::forward<Op>(op)(value);
639      return true;
640    }
641    template <typename U>
642    detail::EnableIfElement<bool, U, ValidTypes...> operator()(U&& value) {
643      std::forward<Op>(op)(std::forward<U>(value));
644      return true;
645    }
646  };
647};
648
649}  // namespace rpc
650}  // namespace pdx
651}  // namespace android
652
653// Overloads of std::get<T> and std::get<I> for android::pdx::rpc::Variant.
654namespace std {
655
656template <typename T, typename... Types>
657inline T& get(::android::pdx::rpc::Variant<Types...>& v) {
658  return *v.template get<T>();
659}
660template <typename T, typename... Types>
661inline T&& get(::android::pdx::rpc::Variant<Types...>&& v) {
662  return std::move(*v.template get<T>());
663}
664template <typename T, typename... Types>
665inline const T& get(const ::android::pdx::rpc::Variant<Types...>& v) {
666  return *v.template get<T>();
667}
668template <std::size_t I, typename... Types>
669inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get(
670    ::android::pdx::rpc::Variant<Types...>& v) {
671  return *v.template get<I>();
672}
673template <std::size_t I, typename... Types>
674inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>&& get(
675    ::android::pdx::rpc::Variant<Types...>&& v) {
676  return std::move(*v.template get<I>());
677}
678template <std::size_t I, typename... Types>
679inline const ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get(
680    const ::android::pdx::rpc::Variant<Types...>& v) {
681  return *v.template get<I>();
682}
683
684}  // namespace std
685
686#endif  // ANDROID_PDX_RPC_VARIANT_H_
687