Home | History | Annotate | Download | only in rpc
      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