• 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_.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_.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) noexcept
451       : index_{other.index_}, value_{std::move(other.value_), other.index_} {}
452 
453 // Recent Clang versions has a regression that produces bogus
454 // unused-lambda-capture warning. Suppress the warning as a temporary
455 // workaround. http://b/71356631
456 #pragma clang diagnostic push
457 #pragma clang diagnostic ignored "-Wunused-lambda-capture"
458   // Copy and move construction from Variant types. Each element of OtherTypes
459   // must be convertible to an element of Types.
460   template <typename... OtherTypes>
461   explicit Variant(const Variant<OtherTypes...>& other) {
462     other.Visit([this](const auto& value) { Construct(value); });
463   }
464 #pragma clang diagnostic pop
465 
466   template <typename... OtherTypes>
467   explicit Variant(Variant<OtherTypes...>&& other) {
468     other.Visit([this](auto&& value) { Construct(std::move(value)); });
469   }
470 
471   Variant& operator=(const Variant& other) {
472     other.Visit([this](const auto& value) { *this = value; });
473     return *this;
474   }
475   Variant& operator=(Variant&& other) noexcept {
476     other.Visit([this](auto&& value) { *this = std::move(value); });
477     return *this;
478   }
479 
480   // Construction from non-Variant types.
481   template <typename T, typename = EnableIfAssignable<void, T>>
482   explicit Variant(T&& value)
483       : Variant(std::forward<T>(value), SelectConstructor<T>{}) {}
484 
485   // Performs assignment from type T belonging to Types. This overload takes
486   // priority to prevent implicit conversion in cases where T is implicitly
487   // convertible to multiple elements of Types.
488   template <typename T>
489   EnableIfElement<Variant&, T> operator=(T&& value) {
490     Assign(DecayedTypeTag<T>{}, std::forward<T>(value));
491     return *this;
492   }
493 
494   // Performs assignment from type T not belonging to Types. This overload
495   // matches in cases where conversion is the only viable option.
496   template <typename T>
497   EnableIfConvertible<Variant&, T> operator=(T&& value) {
498     Assign(std::forward<T>(value));
499     return *this;
500   }
501 
502   // Handles assignment from the empty type. This overload supports assignment
503   // in visitors using generic lambdas.
504   Variant& operator=(EmptyVariant) {
505     Destruct();
506     return *this;
507   }
508 
509   // Assignment from Variant types. Each element of OtherTypes must be
510   // convertible to an element of Types. Forwards through non-Variant assignment
511   // operators to apply conversion checks.
512   template <typename... OtherTypes>
513   Variant& operator=(const Variant<OtherTypes...>& other) {
514     other.Visit([this](const auto& value) { *this = value; });
515     return *this;
516   }
517   template <typename... OtherTypes>
518   Variant& operator=(Variant<OtherTypes...>&& other) {
519     other.Visit([this](auto&& value) { *this = std::move(value); });
520     return *this;
521   }
522 
523   // Becomes the target type, constructing a new element from the given
524   // arguments if necessary. No action is taken if the active element is already
525   // the target type. Otherwise the active element is destroyed and replaced by
526   // constructing an element of the new type using |Args|. An invalid target
527   // type index results in an empty Variant.
528   template <typename... Args>
529   void Become(std::int32_t target_index, Args&&... args) {
530     if (target_index != index()) {
531       Destruct();
532       index_ = value_.Become(target_index, std::forward<Args>(args)...)
533                    ? target_index
534                    : kEmptyIndex;
535     }
536   }
537 
538   // Invokes |Op| on the active element. If the Variant is empty |Op| is invoked
539   // on EmptyVariant.
540   template <typename Op>
541   decltype(auto) Visit(Op&& op) {
542     return value_.Visit(index_, std::forward<Op>(op));
543   }
544   template <typename Op>
545   decltype(auto) Visit(Op&& op) const {
546     return value_.Visit(index_, std::forward<Op>(op));
547   }
548 
549   // Index returned when the Variant is empty.
550   enum : std::int32_t { kEmptyIndex = -1 };
551 
552   // Returns the index of the given type.
553   template <typename T>
554   constexpr std::int32_t index_of() const {
555     static_assert(HasType<T>::value, "T is not an element type of Variant.");
556     return value_.index(DecayedTypeTag<T>{});
557   }
558 
559   // Returns the index of the active type. If the Variant is empty -1 is
560   // returned.
561   std::int32_t index() const { return index_; }
562 
563   // Returns true if the given type is active, false otherwise.
564   template <typename T>
565   bool is() const {
566     static_assert(HasType<T>::value, "T is not an element type of Variant.");
567     return index() == index_of<T>();
568   }
569 
570   // Returns true if the Variant is empty, false otherwise.
571   bool empty() const { return index() == kEmptyIndex; }
572 
573   // Element accessors. Returns a pointer to the active value if the given
574   // type/index is active, otherwise nullptr is returned.
575   template <typename T>
576   T* get() {
577     if (is<T>())
578       return &value_.get(DecayedTypeTag<T>{});
579     else
580       return nullptr;
581   }
582   template <typename T>
583   const T* get() const {
584     if (is<T>())
585       return &value_.template get(DecayedTypeTag<T>{});
586     else
587       return nullptr;
588   }
589   template <std::size_t I>
590   TypeForIndex<I>* get() {
591     if (is<TypeForIndex<I>>())
592       return &value_.get(TypeTagForIndex<I>{});
593     else
594       return nullptr;
595   }
596   template <std::size_t I>
597   const TypeForIndex<I>* get() const {
598     if (is<TypeForIndex<I>>())
599       return &value_.template get(TypeTagForIndex<I>{});
600     else
601       return nullptr;
602   }
603 
604  private:
605   std::int32_t index_ = kEmptyIndex;
606   detail::Union<std::decay_t<Types>...> value_;
607 
608   // Constructs an element from the given arguments and sets the Variant to the
609   // resulting type.
610   template <typename... Args>
611   void Construct(Args&&... args) {
612     index_ = value_.template Construct(std::forward<Args>(args)...);
613   }
614   void Construct(EmptyVariant) {}
615 
616   // Destroys the active element of the Variant.
617   void Destruct() {
618     value_.Destruct(index_);
619     index_ = kEmptyIndex;
620   }
621 
622   // Assigns the Variant when non-empty and the current type matches the target
623   // type, otherwise destroys the current value and constructs a element of the
624   // new type. Tagged assignment is used when T is an element of the Variant to
625   // prevent implicit conversion in cases where T is implicitly convertible to
626   // multiple element types.
627   template <typename T, typename U>
628   void Assign(TypeTag<T>, U&& value) {
629     if (!value_.template Assign(TypeTag<T>{}, index_, std::forward<U>(value))) {
630       Destruct();
631       Construct(TypeTag<T>{}, std::forward<U>(value));
632     }
633   }
634   template <typename T>
635   void Assign(T&& value) {
636     if (!value_.template Assign(index_, std::forward<T>(value))) {
637       Destruct();
638       Construct(std::forward<T>(value));
639     }
640   }
641 };
642 
643 // Utility type to extract/convert values from a variant. This class simplifies
644 // conditional logic to get/move/swap/action values from a variant when one or
645 // more elements are compatible with the destination type.
646 //
647 // Example:
648 //    Variant<int, bool, std::string> v(10);
649 //    bool bool_value;
650 //    if (IfAnyOf<int, bool>::Get(v, &bool_value)) {
651 //      DoSomething(bool_value);
652 //    } else {
653 //      HandleInvalidType();
654 //    }
655 //    IfAnyOf<int>::Call(v, [](const auto& value) { DoSomething(value); });
656 //
657 template <typename... ValidTypes>
658 struct IfAnyOf {
659   // Calls Op on the underlying value of the variant and returns true when the
660   // variant is a valid type, otherwise does nothing and returns false.
661   template <typename Op, typename... Types>
662   static bool Call(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   template <typename Op, typename... Types>
669   static bool Call(const Variant<Types...>* variant, Op&& op) {
670     static_assert(
671         detail::Set<Types...>::template IsSubset<ValidTypes...>::value,
672         "ValidTypes may only contain element types from the Variant.");
673     return variant->Visit(CallOp<Op>{std::forward<Op>(op)});
674   }
675 
676   // Gets/converts the underlying value of the variant to type T and returns
677   // true when the variant is a valid type, otherwise does nothing and returns
678   // false.
679   template <typename T, typename... Types>
680   static bool Get(const Variant<Types...>* variant, T* value_out) {
681     return Call(variant,
682                 [value_out](const auto& value) { *value_out = value; });
683   }
684 
685   // Moves the underlying value of the variant and returns true when the variant
686   // is a valid type, otherwise does nothing and returns false.
687   template <typename T, typename... Types>
688   static bool Take(Variant<Types...>* variant, T* value_out) {
689     return Call(variant,
690                 [value_out](auto&& value) { *value_out = std::move(value); });
691   }
692 
693   // Swaps the underlying value of the variant with |*value_out| and returns
694   // true when the variant is a valid type, otherwise does nothing and returns
695   // false.
696   template <typename T, typename... Types>
697   static bool Swap(Variant<Types...>* variant, T* value_out) {
698     return Call(variant,
699                 [value_out](auto&& value) { std::swap(*value_out, value); });
700   }
701 
702  private:
703   template <typename Op>
704   struct CallOp {
705     Op&& op;
706     template <typename U>
707     detail::EnableIfNotElement<bool, U, ValidTypes...> operator()(U&&) {
708       return false;
709     }
710     template <typename U>
711     detail::EnableIfElement<bool, U, ValidTypes...> operator()(const U& value) {
712       std::forward<Op>(op)(value);
713       return true;
714     }
715     template <typename U>
716     detail::EnableIfElement<bool, U, ValidTypes...> operator()(U&& value) {
717       std::forward<Op>(op)(std::forward<U>(value));
718       return true;
719     }
720   };
721 };
722 
723 }  // namespace rpc
724 }  // namespace pdx
725 }  // namespace android
726 
727 // Overloads of std::get<T> and std::get<I> for android::pdx::rpc::Variant.
728 namespace std {
729 
730 template <typename T, typename... Types>
731 inline T& get(::android::pdx::rpc::Variant<Types...>& v) {
732   return *v.template get<T>();
733 }
734 template <typename T, typename... Types>
735 inline T&& get(::android::pdx::rpc::Variant<Types...>&& v) {
736   return std::move(*v.template get<T>());
737 }
738 template <typename T, typename... Types>
739 inline const T& get(const ::android::pdx::rpc::Variant<Types...>& v) {
740   return *v.template get<T>();
741 }
742 template <std::size_t I, typename... Types>
743 inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get(
744     ::android::pdx::rpc::Variant<Types...>& v) {
745   return *v.template get<I>();
746 }
747 template <std::size_t I, typename... Types>
748 inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>&& get(
749     ::android::pdx::rpc::Variant<Types...>&& v) {
750   return std::move(*v.template get<I>());
751 }
752 template <std::size_t I, typename... Types>
753 inline const ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get(
754     const ::android::pdx::rpc::Variant<Types...>& v) {
755   return *v.template get<I>();
756 }
757 
758 }  // namespace std
759 
760 #endif  // ANDROID_PDX_RPC_VARIANT_H_
761