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