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