Nullable.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <folly/Poly.h>
  18. #include <folly/poly/Regular.h>
  19. namespace folly {
  20. namespace poly {
  21. /**
  22. * A `Poly` interface that can be used to make Poly objects initializable from
  23. * `nullptr` (to create an empty `Poly`) and equality comparable to `nullptr`
  24. * (to test for emptiness).
  25. */
  26. struct INullablePointer : PolyExtends<IEqualityComparable> {
  27. template <class Base>
  28. struct Interface : Base {
  29. Interface() = default;
  30. using Base::Base;
  31. /* implicit */ Interface(std::nullptr_t) : Base{} {
  32. static_assert(
  33. std::is_default_constructible<PolySelf<Base>>::value,
  34. "Cannot initialize a non-default constructible Poly with nullptr");
  35. }
  36. PolySelf<Base>& operator=(std::nullptr_t) {
  37. static_assert(
  38. std::is_default_constructible<PolySelf<Base>>::value,
  39. "Cannot initialize a non-default constructible Poly with nullptr");
  40. auto& self = static_cast<PolySelf<Base>&>(*this);
  41. self = PolySelf<Base>();
  42. return self;
  43. }
  44. friend bool operator==(
  45. std::nullptr_t,
  46. PolySelf<Base> const& self) noexcept {
  47. return poly_empty(self);
  48. }
  49. friend bool operator==(
  50. PolySelf<Base> const& self,
  51. std::nullptr_t) noexcept {
  52. return poly_empty(self);
  53. }
  54. friend bool operator!=(
  55. std::nullptr_t,
  56. PolySelf<Base> const& self) noexcept {
  57. return !poly_empty(self);
  58. }
  59. friend bool operator!=(
  60. PolySelf<Base> const& self,
  61. std::nullptr_t) noexcept {
  62. return !poly_empty(self);
  63. }
  64. };
  65. };
  66. /**
  67. * A `Poly` interface that can be used to make `Poly` objects contextually
  68. * convertible to `bool` (`true` if and only if non-empty). It also gives
  69. * `Poly` objects a unary logical negation operator.
  70. */
  71. struct IBooleanTestable : PolyExtends<> {
  72. template <class Base>
  73. struct Interface : Base {
  74. constexpr bool operator!() const noexcept {
  75. return poly_empty(*this);
  76. }
  77. constexpr explicit operator bool() const noexcept {
  78. return !!*this;
  79. }
  80. };
  81. };
  82. } // namespace poly
  83. } // namespace folly