DiscriminatedPtrDetail.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright 2011-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 <type_traits>
  18. #include <utility>
  19. #include <folly/functional/Invoke.h>
  20. namespace folly {
  21. namespace dptr_detail {
  22. /**
  23. * Given a target type and a list of types, return the 1-based index of the
  24. * type in the list of types. Fail to compile if the target type doesn't
  25. * appear in the list.
  26. *
  27. * GetIndex<int, void, char, int>::value == 3
  28. * GetIndex<int, void, char>::value -> fails to compile
  29. */
  30. template <typename... Types>
  31. struct GetTypeIndex;
  32. // When recursing, we never reach the 0- or 1- template argument base case
  33. // unless the target type is not in the list. If the target type is in the
  34. // list, we stop recursing when it is at the head of the remaining type
  35. // list via the GetTypeIndex<T, T, Types...> partial specialization.
  36. template <typename T, typename... Types>
  37. struct GetTypeIndex<T, T, Types...> {
  38. static const size_t value = 1;
  39. };
  40. template <typename T, typename U, typename... Types>
  41. struct GetTypeIndex<T, U, Types...> {
  42. static const size_t value = 1 + GetTypeIndex<T, Types...>::value;
  43. };
  44. // Generalize std::is_same for variable number of type arguments
  45. template <typename... Types>
  46. struct IsSameType;
  47. template <>
  48. struct IsSameType<> {
  49. static const bool value = true;
  50. };
  51. template <typename T>
  52. struct IsSameType<T> {
  53. static const bool value = true;
  54. };
  55. template <typename T, typename U, typename... Types>
  56. struct IsSameType<T, U, Types...> {
  57. static const bool value =
  58. std::is_same<T, U>::value && IsSameType<U, Types...>::value;
  59. };
  60. // Define type as the type of all T in (non-empty) Types..., asserting that
  61. // all types in Types... are the same.
  62. template <typename... Types>
  63. struct SameType;
  64. template <typename T, typename... Types>
  65. struct SameType<T, Types...> {
  66. typedef T type;
  67. static_assert(
  68. IsSameType<T, Types...>::value,
  69. "Not all types in pack are the same");
  70. };
  71. // Determine the result type of applying a visitor of type V on a pointer
  72. // to type T.
  73. template <typename V, typename T>
  74. struct VisitorResult1 {
  75. typedef invoke_result_t<V, T*> type;
  76. };
  77. // Determine the result type of applying a visitor of type V on a const pointer
  78. // to type T.
  79. template <typename V, typename T>
  80. struct ConstVisitorResult1 {
  81. typedef invoke_result_t<V, const T*> type;
  82. };
  83. // Determine the result type of applying a visitor of type V on pointers of
  84. // all types in Types..., asserting that the type is the same for all types
  85. // in Types...
  86. template <typename V, typename... Types>
  87. struct VisitorResult {
  88. typedef
  89. typename SameType<typename VisitorResult1<V, Types>::type...>::type type;
  90. };
  91. // Determine the result type of applying a visitor of type V on const pointers
  92. // of all types in Types..., asserting that the type is the same for all types
  93. // in Types...
  94. template <typename V, typename... Types>
  95. struct ConstVisitorResult {
  96. typedef
  97. typename SameType<typename ConstVisitorResult1<V, Types>::type...>::type
  98. type;
  99. };
  100. template <size_t index, typename V, typename R, typename... Types>
  101. struct ApplyVisitor1;
  102. template <typename V, typename R, typename T, typename... Types>
  103. struct ApplyVisitor1<1, V, R, T, Types...> {
  104. R operator()(size_t, V&& visitor, void* ptr) const {
  105. return visitor(static_cast<T*>(ptr));
  106. }
  107. };
  108. template <size_t index, typename V, typename R, typename T, typename... Types>
  109. struct ApplyVisitor1<index, V, R, T, Types...> {
  110. R operator()(size_t runtimeIndex, V&& visitor, void* ptr) const {
  111. return runtimeIndex == 1
  112. ? visitor(static_cast<T*>(ptr))
  113. : ApplyVisitor1<index - 1, V, R, Types...>()(
  114. runtimeIndex - 1, std::forward<V>(visitor), ptr);
  115. }
  116. };
  117. template <size_t index, typename V, typename R, typename... Types>
  118. struct ApplyConstVisitor1;
  119. template <typename V, typename R, typename T, typename... Types>
  120. struct ApplyConstVisitor1<1, V, R, T, Types...> {
  121. R operator()(size_t, V&& visitor, void* ptr) const {
  122. return visitor(static_cast<const T*>(ptr));
  123. }
  124. };
  125. template <size_t index, typename V, typename R, typename T, typename... Types>
  126. struct ApplyConstVisitor1<index, V, R, T, Types...> {
  127. R operator()(size_t runtimeIndex, V&& visitor, void* ptr) const {
  128. return runtimeIndex == 1
  129. ? visitor(static_cast<const T*>(ptr))
  130. : ApplyConstVisitor1<index - 1, V, R, Types...>()(
  131. runtimeIndex - 1, std::forward<V>(visitor), ptr);
  132. }
  133. };
  134. template <typename V, typename... Types>
  135. using ApplyVisitor = ApplyVisitor1<
  136. sizeof...(Types),
  137. V,
  138. typename VisitorResult<V, Types...>::type,
  139. Types...>;
  140. template <typename V, typename... Types>
  141. using ApplyConstVisitor = ApplyConstVisitor1<
  142. sizeof...(Types),
  143. V,
  144. typename ConstVisitorResult<V, Types...>::type,
  145. Types...>;
  146. } // namespace dptr_detail
  147. } // namespace folly