1 // Boost result_of library
3 // Copyright Douglas Gregor 2003-2004. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
9 // To run the default test:
10 // $ cd libs/utility/test && bjam
11 // To test decltype on g++ 2.7:
12 // $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
14 #include <boost/config.hpp>
16 // For more information, see http://www.boost.org/libs/utility
17 #include <boost/utility/result_of.hpp>
19 #include <boost/static_assert.hpp>
20 #include <boost/type_traits/is_same.hpp>
22 struct int_result_type
24 typedef int result_type
;
25 result_type
operator()(float);
30 template<typename F
> struct result
{ typedef int type
; };
31 result
<int_result_of(double)>::type
operator()(double);
32 result
<const int_result_of(double)>::type
operator()(double) const;
33 result
<int_result_of()>::type
operator()();
34 result
<volatile int_result_of()>::type
operator()() volatile;
37 struct int_result_type_and_float_result_of_and_char_return
39 typedef int result_type
;
40 template<typename F
> struct result
{ typedef float type
; };
41 char operator()(char);
45 struct int_result_type_template
47 typedef int result_type
;
48 result_type
operator()(float);
52 struct int_result_of_template
54 template<typename F
> struct result
;
55 template<typename This
, typename That
> struct result
<This(That
)> { typedef int type
; };
56 typename result
<int_result_of_template
<T
>(double)>::type
operator()(double);
57 typename result
<const int_result_of_template
<T
>(double)>::type
operator()(double) const;
58 typename result
<int_result_of_template
<T
>(double)>::type
operator()();
59 typename result
<volatile int_result_of_template
<T
>(double)>::type
operator()() volatile;
63 struct int_result_type_and_float_result_of_and_char_return_template
65 typedef int result_type
;
66 template<typename F
> struct result
;
67 template<typename This
, typename That
> struct result
<This(That
)> { typedef float type
; };
68 char operator()(char);
72 struct cv_overload_check
{};
74 struct result_of_member_function_template
76 template<typename F
> struct result
;
78 template<typename This
, typename That
> struct result
<This(That
)> { typedef That type
; };
79 template<class T
> typename result
<result_of_member_function_template(T
)>::type
operator()(T
);
81 template<typename This
, typename That
> struct result
<const This(That
)> { typedef cv_overload_check
<const That
> type
; };
82 template<class T
> typename result
<const result_of_member_function_template(T
)>::type
operator()(T
) const;
84 template<typename This
, typename That
> struct result
<volatile This(That
)> { typedef cv_overload_check
<volatile That
> type
; };
85 template<class T
> typename result
<volatile result_of_member_function_template(T
)>::type
operator()(T
) volatile;
87 template<typename This
, typename That
> struct result
<const volatile This(That
)> { typedef cv_overload_check
<const volatile That
> type
; };
88 template<class T
> typename result
<const volatile result_of_member_function_template(T
)>::type
operator()(T
) const volatile;
90 template<typename This
, typename That
> struct result
<This(That
&, That
)> { typedef That
& type
; };
91 template<class T
> typename result
<result_of_member_function_template(T
&, T
)>::type
operator()(T
&, T
);
93 template<typename This
, typename That
> struct result
<This(That
const &, That
)> { typedef That
const & type
; };
94 template<class T
> typename result
<result_of_member_function_template(T
const &, T
)>::type
operator()(T
const &, T
);
96 template<typename This
, typename That
> struct result
<This(That
volatile &, That
)> { typedef That
volatile & type
; };
97 template<class T
> typename result
<result_of_member_function_template(T
volatile &, T
)>::type
operator()(T
volatile &, T
);
99 template<typename This
, typename That
> struct result
<This(That
const volatile &, That
)> { typedef That
const volatile & type
; };
100 template<class T
> typename result
<result_of_member_function_template(T
const volatile &, T
)>::type
operator()(T
const volatile &, T
);
103 struct no_result_type_or_result
105 short operator()(double);
106 cv_overload_check
<const short> operator()(double) const;
107 cv_overload_check
<volatile short> operator()(double) volatile;
108 cv_overload_check
<const volatile short> operator()(double) const volatile;
110 cv_overload_check
<const int> operator()() const;
111 cv_overload_check
<volatile int> operator()() volatile;
112 cv_overload_check
<const volatile int> operator()() const volatile;
113 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
114 short operator()(int&&);
115 int operator()(int&);
116 long operator()(int const&);
121 struct no_result_type_or_result_template
123 short operator()(double);
124 cv_overload_check
<const short> operator()(double) const;
125 cv_overload_check
<volatile short> operator()(double) volatile;
126 cv_overload_check
<const volatile short> operator()(double) const volatile;
128 cv_overload_check
<const int> operator()() const;
129 cv_overload_check
<volatile int> operator()() volatile;
130 cv_overload_check
<const volatile int> operator()() const volatile;
131 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
132 short operator()(int&&);
133 int operator()(int&);
134 long operator()(int const&);
138 // sfinae_tests are derived from example code from Joel de Guzman,
139 // which demonstrated the interaction between result_of and SFINAE.
140 template <typename F
, typename Arg
>
141 typename
boost::result_of
<F(Arg
const&)>::type
142 sfinae_test(F f
, Arg
const& arg
)
147 template <typename F
, typename Arg
>
148 typename
boost::result_of
<F(Arg
&)>::type
149 sfinae_test(F f
, Arg
& arg
)
154 int sfinae_test_f(int& i
)
163 using namespace boost
;
165 typedef int (*func_ptr
)(float, double);
166 typedef int (&func_ref
)(float, double);
167 typedef int (*func_ptr_0
)();
168 typedef int (&func_ref_0
)();
169 typedef void (*func_ptr_void
)(float, double);
170 typedef void (&func_ref_void
)(float, double);
171 typedef void (*func_ptr_void_0
)();
172 typedef void (&func_ref_void_0
)();
173 typedef int (X::*mem_func_ptr
)(float);
174 typedef int (X::*mem_func_ptr_c
)(float) const;
175 typedef int (X::*mem_func_ptr_v
)(float) volatile;
176 typedef int (X::*mem_func_ptr_cv
)(float) const volatile;
177 typedef int (X::*mem_func_ptr_0
)();
179 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type(float)>::type
, int>::value
));
180 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of(double)>::type
, int>::value
));
181 BOOST_STATIC_ASSERT((is_same
<result_of
<const int_result_of(double)>::type
, int>::value
));
182 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type_template
<void>(float)>::type
, int>::value
));
183 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of_template
<void>(double)>::type
, int>::value
));
184 BOOST_STATIC_ASSERT((is_same
<result_of
<const int_result_of_template
<void>(double)>::type
, int>::value
));
186 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_type(float)>::type
, int>::value
));
187 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_of(double)>::type
, int>::value
));
188 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<const int_result_of(double)>::type
, int>::value
));
189 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_type_template
<void>(float)>::type
, int>::value
));
190 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_of_template
<void>(double)>::type
, int>::value
));
191 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<const int_result_of_template
<void>(double)>::type
, int>::value
));
193 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_of(void)>::type
, void>::value
));
194 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<volatile int_result_of(void)>::type
, void>::value
));
195 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_of_template
<void>(void)>::type
, void>::value
));
196 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<volatile int_result_of_template
<void>(void)>::type
, void>::value
));
198 // Prior to decltype, result_of could not deduce the return type
199 // of nullary function objects unless they exposed a result_type.
200 #if defined(BOOST_RESULT_OF_USE_DECLTYPE)
201 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of(void)>::type
, int>::value
));
202 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile int_result_of(void)>::type
, int>::value
));
203 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of_template
<void>(void)>::type
, int>::value
));
204 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile int_result_of_template
<void>(void)>::type
, int>::value
));
206 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of(void)>::type
, void>::value
));
207 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile int_result_of(void)>::type
, void>::value
));
208 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_of_template
<void>(void)>::type
, void>::value
));
209 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile int_result_of_template
<void>(void)>::type
, void>::value
));
212 // Prior to decltype, result_of ignored a nested result<> if
213 // result_type was defined. After decltype, result_of deduces the
214 // actual return type of the function object, ignoring both
215 // result<> and result_type.
216 #if defined(BOOST_RESULT_OF_USE_DECLTYPE)
217 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type_and_float_result_of_and_char_return(char)>::type
, char>::value
));
218 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type_and_float_result_of_and_char_return_template
<void>(char)>::type
, char>::value
));
220 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type_and_float_result_of_and_char_return(char)>::type
, int>::value
));
221 BOOST_STATIC_ASSERT((is_same
<result_of
<int_result_type_and_float_result_of_and_char_return_template
<void>(char)>::type
, int>::value
));
224 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_type_and_float_result_of_and_char_return(char)>::type
, int>::value
));
225 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<int_result_type_and_float_result_of_and_char_return_template
<void>(char)>::type
, int>::value
));
227 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ptr(char, float)>::type
, int>::value
));
228 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ref(char, float)>::type
, int>::value
));
229 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ptr_0()>::type
, int>::value
));
230 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ref_0()>::type
, int>::value
));
231 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ptr_void(char, float)>::type
, void>::value
));
232 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ref_void(char, float)>::type
, void>::value
));
233 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ptr_void_0()>::type
, void>::value
));
234 BOOST_STATIC_ASSERT((is_same
<result_of
<func_ref_void_0()>::type
, void>::value
));
235 BOOST_STATIC_ASSERT((is_same
<result_of
<mem_func_ptr(X
,char)>::type
, int>::value
));
236 BOOST_STATIC_ASSERT((is_same
<result_of
<mem_func_ptr_c(X
,char)>::type
, int>::value
));
237 BOOST_STATIC_ASSERT((is_same
<result_of
<mem_func_ptr_v(X
,char)>::type
, int>::value
));
238 BOOST_STATIC_ASSERT((is_same
<result_of
<mem_func_ptr_cv(X
,char)>::type
, int>::value
));
239 BOOST_STATIC_ASSERT((is_same
<result_of
<mem_func_ptr_0(X
)>::type
, int>::value
));
241 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ptr(char, float)>::type
, int>::value
));
242 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ref(char, float)>::type
, int>::value
));
243 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ptr_0()>::type
, int>::value
));
244 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ref_0()>::type
, int>::value
));
245 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ptr_void(char, float)>::type
, void>::value
));
246 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ref_void(char, float)>::type
, void>::value
));
247 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ptr_void_0()>::type
, void>::value
));
248 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ref_void_0()>::type
, void>::value
));
249 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<mem_func_ptr(X
,char)>::type
, int>::value
));
250 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<mem_func_ptr_c(X
,char)>::type
, int>::value
));
251 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<mem_func_ptr_v(X
,char)>::type
, int>::value
));
252 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<mem_func_ptr_cv(X
,char)>::type
, int>::value
));
253 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<mem_func_ptr_0(X
)>::type
, int>::value
));
254 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ptr(void)>::type
, int>::value
));
255 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<func_ref(void)>::type
, int>::value
));
257 BOOST_STATIC_ASSERT((is_same
<result_of
<result_of_member_function_template(double)>::type
, double>::value
));
258 BOOST_STATIC_ASSERT((is_same
<result_of
<const result_of_member_function_template(double)>::type
, cv_overload_check
<const double> >::value
));
259 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile result_of_member_function_template(double)>::type
, cv_overload_check
<volatile double> >::value
));
260 BOOST_STATIC_ASSERT((is_same
<result_of
<const volatile result_of_member_function_template(double)>::type
, cv_overload_check
<const volatile double> >::value
));
261 BOOST_STATIC_ASSERT((is_same
<result_of
<result_of_member_function_template(int &, int)>::type
, int &>::value
));
262 BOOST_STATIC_ASSERT((is_same
<result_of
<result_of_member_function_template(int const &, int)>::type
, int const &>::value
));
263 BOOST_STATIC_ASSERT((is_same
<result_of
<result_of_member_function_template(int volatile &, int)>::type
, int volatile &>::value
));
264 BOOST_STATIC_ASSERT((is_same
<result_of
<result_of_member_function_template(int const volatile &, int)>::type
, int const volatile &>::value
));
266 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<result_of_member_function_template(double)>::type
, double>::value
));
267 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<const result_of_member_function_template(double)>::type
, cv_overload_check
<const double> >::value
));
268 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<volatile result_of_member_function_template(double)>::type
, cv_overload_check
<volatile double> >::value
));
269 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<const volatile result_of_member_function_template(double)>::type
, cv_overload_check
<const volatile double> >::value
));
270 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<result_of_member_function_template(int &, int)>::type
, int &>::value
));
271 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<result_of_member_function_template(int const &, int)>::type
, int const &>::value
));
272 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<result_of_member_function_template(int volatile &, int)>::type
, int volatile &>::value
));
273 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<result_of_member_function_template(int const volatile &, int)>::type
, int const volatile &>::value
));
275 typedef int (*pf_t
)(int);
276 BOOST_STATIC_ASSERT((is_same
<result_of
<pf_t(int)>::type
, int>::value
));
277 BOOST_STATIC_ASSERT((is_same
<result_of
<pf_t
const(int)>::type
,int>::value
));
279 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<pf_t(int)>::type
, int>::value
));
280 BOOST_STATIC_ASSERT((is_same
<tr1_result_of
<pf_t
const(int)>::type
,int>::value
));
282 #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
283 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result(double)>::type
, short>::value
));
284 BOOST_STATIC_ASSERT((is_same
<result_of
<const no_result_type_or_result(double)>::type
, cv_overload_check
<const short> >::value
));
285 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile no_result_type_or_result(double)>::type
, cv_overload_check
<volatile short> >::value
));
286 BOOST_STATIC_ASSERT((is_same
<result_of
<const volatile no_result_type_or_result(double)>::type
, cv_overload_check
<const volatile short> >::value
));
287 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result(void)>::type
, int>::value
));
288 BOOST_STATIC_ASSERT((is_same
<result_of
<const no_result_type_or_result(void)>::type
, cv_overload_check
<const int> >::value
));
289 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile no_result_type_or_result(void)>::type
, cv_overload_check
<volatile int> >::value
));
290 BOOST_STATIC_ASSERT((is_same
<result_of
<const volatile no_result_type_or_result(void)>::type
, cv_overload_check
<const volatile int> >::value
));
292 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result_template
<void>(double)>::type
, short>::value
));
293 BOOST_STATIC_ASSERT((is_same
<result_of
<const no_result_type_or_result_template
<void>(double)>::type
, cv_overload_check
<const short> >::value
));
294 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile no_result_type_or_result_template
<void>(double)>::type
, cv_overload_check
<volatile short> >::value
));
295 BOOST_STATIC_ASSERT((is_same
<result_of
<const volatile no_result_type_or_result_template
<void>(double)>::type
, cv_overload_check
<const volatile short> >::value
));
296 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result_template
<void>(void)>::type
, int>::value
));
297 BOOST_STATIC_ASSERT((is_same
<result_of
<const no_result_type_or_result_template
<void>(void)>::type
, cv_overload_check
<const int> >::value
));
298 BOOST_STATIC_ASSERT((is_same
<result_of
<volatile no_result_type_or_result_template
<void>(void)>::type
, cv_overload_check
<volatile int> >::value
));
299 BOOST_STATIC_ASSERT((is_same
<result_of
<const volatile no_result_type_or_result_template
<void>(void)>::type
, cv_overload_check
<const volatile int> >::value
));
300 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
301 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result(int&&)>::type
, short>::value
));
302 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result(int&)>::type
, int>::value
));
303 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result(int const&)>::type
, long>::value
));
304 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result_template
<void>(int&&)>::type
, short>::value
));
305 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result_template
<void>(int&)>::type
, int>::value
));
306 BOOST_STATIC_ASSERT((is_same
<result_of
<no_result_type_or_result_template
<void>(int const&)>::type
, long>::value
));
310 #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
312 sfinae_test(sfinae_test_f
, i
);
313 #endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)