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