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