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