• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 namespace android {
9 namespace pdx {
10 namespace rpc {
11 
12 // Type tag denoting an empty variant.
13 struct EmptyVariant {};
14 
15 namespace detail {
16 
17 // Type for matching tagged overloads.
18 template <typename T>
19 struct TypeTag {};
20 
21 // Determines the type of the I-th element of Types....
22 template <std::size_t I, typename... Types>
23 using TypeForIndex = std::tuple_element_t<I, std::tuple<Types...>>;
24 
25 // Determines the type tag for the I-th element of Types....
26 template <std::size_t I, typename... Types>
27 using TypeTagForIndex = TypeTag<TypeForIndex<I, Types...>>;
28 
29 // Enable if T(Args...) is well formed.
30 template <typename R, typename T, typename... Args>
31 using EnableIfConstructible =
32     typename std::enable_if<std::is_constructible<T, Args...>::value, R>::type;
33 // Enable if T(Args...) is not well formed.
34 template <typename R, typename T, typename... Args>
35 using EnableIfNotConstructible =
36     typename std::enable_if<!std::is_constructible<T, Args...>::value, R>::type;
37 
38 // Determines whether T is an element of Types...;
39 template <typename... Types>
40 struct HasType : std::false_type {};
41 template <typename T, typename U>
42 struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
43 template <typename T, typename First, typename... Rest>
44 struct 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...
49 template <typename... Types>
50 struct 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.
64 template <typename... Types>
65 struct ConstructibleCount;
66 template <typename From, typename To>
67 struct ConstructibleCount<From, To>
68     : std::integral_constant<std::size_t,
69                              std::is_constructible<To, From>::value> {};
70 template <typename From, typename First, typename... Rest>
71 struct 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...
77 template <typename R, typename T, typename... Types>
78 using EnableIfElement =
79     typename std::enable_if<HasType<T, Types...>::value, R>::type;
80 // Enable if T is not an element of Types...
81 template <typename R, typename T, typename... Types>
82 using 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...
88 template <typename R, typename T, typename... Types>
89 using 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.
99 template <typename R, typename T, typename... Types>
100 using 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.
106 template <bool CondA, typename SelectA, typename SelectB>
107 using Select = std::conditional_t<CondA, SelectA, SelectB>;
108 
109 // Recursive union type.
110 template <typename... Types>
111 union Union;
112 
113 // Specialization handling a singular type, terminating template recursion.
114 template <typename Type>
115 union 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.
207 template <typename First, typename... Rest>
208 union 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 
354 template <typename... Types>
355 class 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 //
583 template <typename... ValidTypes>
584 struct 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.
654 namespace std {
655 
656 template <typename T, typename... Types>
657 inline T& get(::android::pdx::rpc::Variant<Types...>& v) {
658   return *v.template get<T>();
659 }
660 template <typename T, typename... Types>
661 inline T&& get(::android::pdx::rpc::Variant<Types...>&& v) {
662   return std::move(*v.template get<T>());
663 }
664 template <typename T, typename... Types>
665 inline const T& get(const ::android::pdx::rpc::Variant<Types...>& v) {
666   return *v.template get<T>();
667 }
668 template <std::size_t I, typename... Types>
669 inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get(
670     ::android::pdx::rpc::Variant<Types...>& v) {
671   return *v.template get<I>();
672 }
673 template <std::size_t I, typename... Types>
674 inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>&& get(
675     ::android::pdx::rpc::Variant<Types...>&& v) {
676   return std::move(*v.template get<I>());
677 }
678 template <std::size_t I, typename... Types>
679 inline 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