sfinae_utils.h
Go to the documentation of this file.
1 #ifndef TESSEACT_COMMON_SFINAE_UTILS_H
2 #define TESSEACT_COMMON_SFINAE_UTILS_H
3 
6 #include <type_traits>
7 #include <array>
9 
10 /*
11  * https://stackoverflow.com/questions/257288/templated-check-for-the-existence-of-a-class-member-function
12  *
13  * - Multiple inheritance forces ambiguity of member names.
14  * - SFINAE is used to make aliases to member names.
15  * - Expression SFINAE is used in just one generic has_member that can accept
16  * any alias we pass it.
17  */
18 
19 namespace tesseract_common
20 {
21 // Variadic to force ambiguity of class members. C++11 and up.
22 template <typename... Args>
23 struct ambiguate : public Args...
24 {
25 };
26 
27 template <typename A, typename = void>
28 struct got_type : std::false_type
29 {
30 };
31 
32 template <typename A>
33 struct got_type<A> : std::true_type
34 {
35  using type = A;
36 };
37 
38 template <typename T, T>
39 struct sig_check : std::true_type
40 {
41 };
42 
43 template <typename Alias, typename AmbiguitySeed>
44 struct has_member
45 {
46  template <typename C>
47  static std::array<char, 1>& f(decltype(&C::value));
48  template <typename C>
49  static std::array<char, 2>& f(...);
50 
51  // Make sure the member name is consistently spelled the same.
52  static_assert((sizeof(f<AmbiguitySeed>(nullptr)) == 1),
53  "Member name specified in AmbiguitySeed is different from member name specified in Alias, or wrong "
54  "Alias/AmbiguitySeed has been specified.");
55 
56  static bool const value = sizeof(f<Alias>(nullptr)) == 2;
57 };
58 
68 #define CREATE_MEMBER_CHECK(member) \
69  \
70  template <typename T, typename = std::true_type> \
71  struct Alias_##member; \
72  \
73  template <typename T> \
74  struct Alias_##member<T, std::integral_constant<bool, tesseract_common::got_type<decltype(&T::member)>::value>> \
75  { \
76  static const decltype(&T::member) value; \
77  }; \
78  \
79  struct AmbiguitySeed_##member \
80  { \
81  char member; /* NOLINT */ \
82  }; \
83  \
84  template <typename T> \
85  struct has_member_##member \
86  { \
87  static const bool value = \
88  tesseract_common::has_member<Alias_##member<tesseract_common::ambiguate<T, AmbiguitySeed_##member>>, \
89  Alias_##member<AmbiguitySeed_##member>>::value; \
90  }
91 
99 #define CREATE_MEMBER_FUNC_INVOCABLE_CHECK(func_name, ...) \
100  \
101  template <typename T, typename = std::true_type> \
102  struct has_member_func_invocable_##func_name : std::false_type \
103  { \
104  }; \
105  \
106  template <typename T> \
107  struct has_member_func_invocable_##func_name< \
108  T, \
109  std::integral_constant<bool, std::is_invocable<decltype(&T::func_name), T, __VA_ARGS__>::value>> \
110  : std::true_type \
111  { \
112  };
113 
121 #define CREATE_MEMBER_FUNC_RETURN_TYPE_CHECK(func_name, return_type, ...) \
122  \
123  template <typename T, typename = std::true_type> \
124  struct has_member_func_return_type_##func_name : std::false_type \
125  { \
126  }; \
127  \
128  template <typename T> \
129  struct has_member_func_return_type_##func_name< \
130  T, \
131  std::integral_constant<bool, \
132  std::is_same<typename std::invoke_result<decltype(&T::func_name), T, __VA_ARGS__>::type, \
133  return_type>::value>> : std::true_type \
134  { \
135  };
136 
144 #define CREATE_MEMBER_FUNC_RETURN_TYPE_NOARGS_CHECK(func_name, return_type) \
145  \
146  template <typename T, typename = std::true_type> \
147  struct has_member_func_return_type_##func_name : std::false_type \
148  { \
149  }; \
150  \
151  template <typename T> \
152  struct has_member_func_return_type_##func_name< \
153  T, \
154  std::integral_constant< \
155  bool, \
156  std::is_same<typename std::invoke_result<decltype(&T::func_name), T>::type, return_type>::value>> \
157  : std::true_type \
158  { \
159  };
160 
168 #define CREATE_MEMBER_FUNC_SIGNATURE_CHECK(func_name, return_type, ...) \
169  \
170  template <typename T, typename = std::true_type> \
171  struct has_member_func_signature_##func_name : std::false_type \
172  { \
173  }; \
174  \
175  template <typename T> \
176  struct has_member_func_signature_##func_name< \
177  T, \
178  std::integral_constant< \
179  bool, \
180  std::is_invocable<decltype(&T::func_name), T, __VA_ARGS__>::value && \
181  std::is_same<typename std::invoke_result<decltype(&T::func_name), T, __VA_ARGS__>::type, \
182  return_type>::value>> : std::true_type \
183  { \
184  };
185 
193 #define CREATE_MEMBER_FUNC_SIGNATURE_NOARGS_CHECK(func_name, return_type) \
194  \
195  template <typename T, typename = std::true_type> \
196  struct has_member_func_signature_##func_name : std::false_type \
197  { \
198  }; \
199  \
200  template <typename T> \
201  struct has_member_func_signature_##func_name< \
202  T, \
203  std::integral_constant< \
204  bool, \
205  std::is_invocable<decltype(&T::func_name), T>::value && \
206  std::is_same<typename std::invoke_result<decltype(&T::func_name), T>::type, return_type>::value>> \
207  : std::true_type \
208  { \
209  };
210 
211 } // namespace tesseract_common
212 
213 #endif // TESSEACT_COMMON_SFINAE_UTILS_H
tesseract_common
Definition: allowed_collision_matrix.h:19
macros.h
Common Tesseract Macros.
tesseract_common::got_type
Definition: sfinae_utils.h:28
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
Definition: macros.h:71
tesseract_common::has_member::f
static std::array< char, 1 > & f(decltype(&C::value))
tesseract_common::got_type< A >::type
A type
Definition: sfinae_utils.h:35
TESSERACT_COMMON_IGNORE_WARNINGS_POP
#define TESSERACT_COMMON_IGNORE_WARNINGS_POP
Definition: macros.h:72
tesseract_common::ambiguate
Definition: sfinae_utils.h:23
tesseract_common::has_member
Definition: sfinae_utils.h:44
tesseract_common::sig_check
Definition: sfinae_utils.h:39
tesseract_common::has_member::value
static const bool value
Definition: sfinae_utils.h:56


tesseract_common
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:01:40