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