1 // Boost result_of library
2 
3 //  Copyright Douglas Gregor 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)
7 
8 // For more information, see http://www.boost.org/libs/utility
9 #ifndef BOOST_RESULT_OF_HPP
10 #define BOOST_RESULT_OF_HPP
11 
12 #include <boost/config.hpp>
13 #include <boost/detail/workaround.hpp>
14 #include <boost/type_traits/is_class.hpp>
15 #include <boost/type_traits/is_pointer.hpp>
16 #include <boost/type_traits/is_member_function_pointer.hpp>
17 #include <boost/type_traits/remove_cv.hpp>
18 #include <boost/type_traits/remove_reference.hpp>
19 #include <boost/type_traits/declval.hpp>
20 #include <boost/type_traits/conditional.hpp>
21 #include <boost/type_traits/type_identity.hpp>
22 #include <boost/type_traits/integral_constant.hpp>
23 #include <boost/core/enable_if.hpp>
24 
25 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
26 #  undef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
27 #  define BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
28 #endif
29 #ifdef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
30 #  include <boost/preprocessor/cat.hpp>
31 #  include <boost/preprocessor/iteration/iterate.hpp>
32 #  include <boost/preprocessor/repetition/enum_params.hpp>
33 #  include <boost/preprocessor/repetition/enum_trailing_params.hpp>
34 #  include <boost/preprocessor/repetition/enum_binary_params.hpp>
35 #  include <boost/preprocessor/repetition/enum_shifted_params.hpp>
36 #  include <boost/preprocessor/facilities/intercept.hpp>
37 #endif
38 
39 #ifndef BOOST_UTILITY_DOCS
40 #ifndef BOOST_RESULT_OF_NUM_ARGS
41 #  define BOOST_RESULT_OF_NUM_ARGS 16
42 #endif
43 #endif // BOOST_UTILITY_DOCS
44 
45 // Use the decltype-based version of result_of by default if the compiler
46 // supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
47 // The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE,
48 // BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one!
49 #if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \
50     (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \
51     (defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK))
52 #  error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \
53   BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
54 #endif
55 
56 #ifndef BOOST_UTILITY_DOCS
57 #ifndef BOOST_RESULT_OF_USE_TR1
58 #  ifndef BOOST_RESULT_OF_USE_DECLTYPE
59 #    ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
60 #      ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
61 #        define BOOST_RESULT_OF_USE_DECLTYPE
62 #      else
63 #        define BOOST_RESULT_OF_USE_TR1
64 #      endif
65 #    endif
66 #  endif
67 #endif
68 #endif // BOOST_UTILITY_DOCS
69 
70 namespace boost {
71 
72 template<typename F> struct result_of;
73 template<typename F> struct tr1_result_of; // a TR1-style implementation of result_of
74 
75 #if !defined(BOOST_NO_SFINAE)
76 namespace detail {
77 
78 typedef char result_of_yes_type;      // sizeof(result_of_yes_type) == 1
79 typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type)  == 2
80 
81 template<class T> struct result_of_has_type {};
82 
83 template<class T> struct result_of_has_result_type_impl
84 {
85     template<class U> static result_of_yes_type f( result_of_has_type<typename U::result_type>* );
86     template<class U> static result_of_no_type f( ... );
87 
88     typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
89 };
90 
91 template<class T> struct result_of_has_result_type: result_of_has_result_type_impl<T>::type
92 {
93 };
94 
95 // Work around a nvcc bug by only defining has_result when it's needed.
96 #ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
97 
98 template<template<class> class C> struct result_of_has_template {};
99 
100 template<class T> struct result_of_has_result_impl
101 {
102     template<class U> static result_of_yes_type f( result_of_has_template<U::template result>* );
103     template<class U> static result_of_no_type f( ... );
104 
105     typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
106 };
107 
108 template<class T> struct result_of_has_result: result_of_has_result_impl<T>::type
109 {
110 };
111 
112 #endif
113 
114 template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
115 
116 template<typename F> struct cpp0x_result_of;
117 
118 #ifdef BOOST_NO_SFINAE_EXPR
119 
120 // There doesn't seem to be any other way to turn this off such that the presence of
121 // the user-defined operator,() below doesn't cause spurious warning all over the place,
122 // so unconditionally turn it off.
123 #if BOOST_MSVC
124 #  pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
125 #endif
126 
127 struct result_of_private_type {};
128 
129 struct result_of_weird_type {
130   friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
131 };
132 
133 template<typename T>
134 result_of_no_type result_of_is_private_type(T const &);
135 result_of_yes_type result_of_is_private_type(result_of_private_type);
136 
137 template<typename C>
138 struct result_of_callable_class : C {
139     result_of_callable_class();
140     typedef result_of_private_type const &(*pfn_t)(...);
141     operator pfn_t() const volatile;
142 };
143 
144 template<typename C>
145 struct result_of_wrap_callable_class {
146   typedef result_of_callable_class<C> type;
147 };
148 
149 template<typename C>
150 struct result_of_wrap_callable_class<C const> {
151   typedef result_of_callable_class<C> const type;
152 };
153 
154 template<typename C>
155 struct result_of_wrap_callable_class<C volatile> {
156   typedef result_of_callable_class<C> volatile type;
157 };
158 
159 template<typename C>
160 struct result_of_wrap_callable_class<C const volatile> {
161   typedef result_of_callable_class<C> const volatile type;
162 };
163 
164 template<typename C>
165 struct result_of_wrap_callable_class<C &> {
166   typedef typename result_of_wrap_callable_class<C>::type &type;
167 };
168 
169 template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
170 
171 #else // BOOST_NO_SFINAE_EXPR
172 
173 template<typename T>
174 struct result_of_always_void
175 {
176   typedef void type;
177 };
178 
179 template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
180 
181 #endif // BOOST_NO_SFINAE_EXPR
182 
183 template<typename F>
184 struct result_of_void_impl
185 {
186   typedef void type;
187 };
188 
189 template<typename R>
190 struct result_of_void_impl<R (*)(void)>
191 {
192   typedef R type;
193 };
194 
195 template<typename R>
196 struct result_of_void_impl<R (&)(void)>
197 {
198   typedef R type;
199 };
200 
201 // Determine the return type of a function pointer or pointer to member.
202 template<typename F, typename FArgs>
203 struct result_of_pointer
204   : tr1_result_of_impl<typename remove_cv<F>::type, FArgs, false> { };
205 
206 template<typename F, typename FArgs>
207 struct tr1_result_of_impl<F, FArgs, true>
208 {
209   typedef typename F::result_type type;
210 };
211 
212 template<typename FArgs>
213 struct is_function_with_no_args : false_type {};
214 
215 template<typename F>
216 struct is_function_with_no_args<F(void)> : true_type {};
217 
218 template<typename F, typename FArgs>
219 struct result_of_nested_result : F::template result<FArgs>
220 {};
221 
222 template<typename F, typename FArgs>
223 struct tr1_result_of_impl<F, FArgs, false>
224   : conditional<is_function_with_no_args<FArgs>::value,
225              result_of_void_impl<F>,
226              result_of_nested_result<F, FArgs> >::type
227 {};
228 
229 } // end namespace detail
230 
231 #ifndef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
232 #  include <boost/utility/detail/result_of_variadic.hpp>
233 #else
234 #  define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
235 #  include BOOST_PP_ITERATE()
236 #endif
237 
238 #if 0
239 // inform dependency trackers, as they can't see through macro includes
240 #include <boost/utility/detail/result_of_iterate.hpp>
241 #endif
242 
243 #else
244 #  define BOOST_NO_RESULT_OF 1
245 #endif
246 
247 }
248 
249 #endif // BOOST_RESULT_OF_HPP
250