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_.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