Ticket #9369: has_member_function_callable_with.hpp

File has_member_function_callable_with.hpp, 17.5 KB (added by anonymous, 7 years ago)
Line 
1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/intrusive for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11// sample.h
12
13#if !defined(BOOST_PP_IS_ITERATING)
14
15 #ifndef BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
16 #define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
17
18 #include <boost/intrusive/detail/config_begin.hpp>
19 #include <boost/intrusive/detail/workaround.hpp>
20 #include <boost/intrusive/detail/preprocessor.hpp>
21 #include <boost/intrusive/detail/mpl.hpp>
22 #include <boost/static_assert.hpp>
23 #include <boost/move/move.hpp>
24
25 //Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
26 //wrong SFINAE for GCC 4.2/4.3
27 #if defined(__GNUC__) && !defined(__clang__) && ((__GNUC__*100 + __GNUC_MINOR__*10) >= 340) && ((__GNUC__*100 + __GNUC_MINOR__*10) <= 430)
28 #define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
29 #elif defined(BOOST_INTEL) && (BOOST_INTEL < 1200 )
30 #define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
31 #endif
32
33 namespace boost_intrusive_has_member_function_callable_with {
34
35 struct dont_care
36 {
37 dont_care(...);
38 };
39
40 struct private_type
41 {
42 static private_type p;
43 private_type const &operator,(int) const;
44 };
45
46 typedef char yes_type; // sizeof(yes_type) == 1
47 struct no_type{ char dummy[2]; }; // sizeof(no_type) == 2
48
49 template<typename T>
50 no_type is_private_type(T const &);
51 yes_type is_private_type(private_type const &);
52
53 } //boost_intrusive_has_member_function_callable_with
54
55 #include <boost/intrusive/detail/config_end.hpp>
56
57 #endif //BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
58
59#else //!BOOST_PP_IS_ITERATING
60
61 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
62 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME not defined!"
63 #endif
64
65 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
66 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN not defined!"
67 #endif
68
69 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
70 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!"
71 #endif
72
73 #if BOOST_PP_ITERATION_START() != 0
74 #error "BOOST_PP_ITERATION_START() must be zero (0)"
75 #endif
76
77 #if BOOST_PP_ITERATION() == 0
78
79 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
80
81 template <typename Type>
82 class BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
83 {
84 struct BaseMixin
85 {
86 void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME();
87 };
88
89 struct Base : public ::boost::intrusive::detail::remove_cv<Type>::type, public BaseMixin { Base(); };
90 template <typename T, T t> class Helper{};
91
92 template <typename U>
93 static boost_intrusive_has_member_function_callable_with::no_type deduce
94 (U*, Helper<void (BaseMixin::*)(), &U::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME>* = 0);
95 static boost_intrusive_has_member_function_callable_with::yes_type deduce(...);
96
97 public:
98 static const bool value =
99 sizeof(boost_intrusive_has_member_function_callable_with::yes_type) == sizeof(deduce((Base*)(0)));
100 };
101
102 #if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
103
104 template<typename Fun, bool HasFunc
105 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
106 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl);
107 //!
108
109 template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), class P)>
110 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
111 <Fun, false BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P)>
112 {
113 static const bool value = false;
114 };
115 //!
116
117 #if !defined(_MSC_VER) || (_MSC_VER < 1600)
118
119 #if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
120
121 template<typename Fun>
122 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
123 <Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
124 {
125 //Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
126 //wrong SFINAE for GCC 4.2/4.3
127 static const bool value = true;
128 };
129
130 #else //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
131
132 //Special case for 0 args
133 template< class F
134 , std::size_t N =
135 sizeof((boost::move_detail::declval<F>().
136 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
137 struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
138 {
139 boost_intrusive_has_member_function_callable_with::yes_type dummy;
140 BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
141 };
142
143 //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
144 //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
145 template<class F>
146 struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
147 {
148 boost_intrusive_has_member_function_callable_with::no_type dummy;
149 BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
150 };
151
152 template<typename Fun>
153 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
154 <Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
155 {
156 template<class U>
157 static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>
158 Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
159
160 template <class U>
161 static boost_intrusive_has_member_function_callable_with::no_type Test(...);
162
163 static const bool value = sizeof(Test< Fun >(0))
164 == sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
165 };
166 #endif //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
167
168 #else //#if !defined(_MSC_VER) || (_MSC_VER < 1600)
169 template<typename Fun>
170 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
171 <Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
172 {
173 template<class U>
174 static decltype( boost::move_detail::declval<Fun>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
175 , boost_intrusive_has_member_function_callable_with::yes_type())
176 Test(Fun*);
177
178 template<class U>
179 static boost_intrusive_has_member_function_callable_with::no_type Test(...);
180
181 static const bool value = sizeof(Test<Fun>(0))
182 == sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
183 };
184 #endif //#if !defined(_MSC_VER) || (_MSC_VER < 1600)
185
186 #else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
187
188 template<typename Fun, bool HasFunc, class ...Args>
189 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl);
190
191 template<typename Fun, class ...Args>
192 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
193 <Fun, false, Args...>
194 {
195 static const bool value = false;
196 };
197
198 //Special case for 0 args
199 template< class F
200 , std::size_t N =
201 sizeof((boost::move_detail::declval<F>().
202 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
203 struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
204 {
205 boost_intrusive_has_member_function_callable_with::yes_type dummy;
206 BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
207 };
208
209 //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
210 //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
211 template<class F>
212 struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
213 {
214 boost_intrusive_has_member_function_callable_with::no_type dummy;
215 BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
216 };
217
218 template<typename Fun>
219 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
220 <Fun, true>
221 {
222 template<class U>
223 static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
224 <U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
225
226 template <class U>
227 static boost_intrusive_has_member_function_callable_with::no_type Test(...);
228
229 static const bool value = sizeof(Test< Fun >(0))
230 == sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
231 };
232
233 template<typename Fun, class ...DontCares>
234 struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
235 : Fun
236 {
237 BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )();
238 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
239
240 boost_intrusive_has_member_function_callable_with::private_type
241 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
242 ( DontCares...) const;
243 };
244
245 template<typename Fun, class ...Args>
246 struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
247 <Fun, true , Args...>
248 {
249 template<class T>
250 struct make_dontcare
251 {
252 typedef boost_intrusive_has_member_function_callable_with::dont_care type;
253 };
254
255 typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
256 <Fun, typename make_dontcare<Args>::type...> FunWrap;
257
258 static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
259 sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
260 ( (::boost::move_detail::declval< FunWrap >().
261 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
262 ( ::boost::move_detail::declval<Args>()... ), 0) )
263 )
264 );
265 };
266
267 template<typename Fun, class ...Args>
268 struct BOOST_PP_CAT( has_member_function_callable_with_
269 , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
270 : public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
271 , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
272 < Fun
273 , BOOST_PP_CAT( has_member_function_named_
274 , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )<Fun>::value
275 , Args... >
276 {};
277
278 #endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
279
280 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
281
282 #else //BOOST_PP_ITERATION() == 0
283
284 #if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
285
286 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
287
288 template<typename Fun>
289 struct BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
290 , BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))
291 : Fun
292 {
293 BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
294 , BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))();
295
296 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
297 boost_intrusive_has_member_function_callable_with::private_type
298 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
299 ( BOOST_PP_ENUM(BOOST_PP_ITERATION()
300 , BOOST_INTRUSIVE_PP_IDENTITY
301 , boost_intrusive_has_member_function_callable_with::dont_care)) const;
302 };
303
304 template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class P)>
305 struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
306 , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
307 <Fun, true
308 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), P)
309 BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION())
310 , BOOST_INTRUSIVE_PP_IDENTITY
311 , void)>
312 {
313 typedef BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
314 , BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))<Fun>
315 FunWrap;
316 static bool const value =
317 (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
318 sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
319 ( (boost::move_detail::declval<FunWrap>().
320 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
321 ( BOOST_PP_ENUM( BOOST_PP_ITERATION(), BOOST_INTRUSIVE_PP_DECLVAL, _) ), 0
322 )
323 )
324 )
325 );
326 };
327
328 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
329 #endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
330
331 #endif //BOOST_PP_ITERATION() == 0
332
333 #if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
334
335 #if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
336
337 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
338
339 template<typename Fun
340 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
341 struct BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
342 : public BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
343 <Fun, BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun>::value
344 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P) >
345 {};
346
347 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
348
349 #endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
350
351 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
352 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
353 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
354
355 #endif //#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
356
357#endif //!BOOST_PP_IS_ITERATING