result_of_test.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Boost result_of library
  2. // Copyright Douglas Gregor 2003-2004. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // Examples:
  7. // To run the default test:
  8. // $ cd libs/utility/test && bjam
  9. // To test decltype on g++ 2.7:
  10. // $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
  11. #include <boost/config.hpp>
  12. // For more information, see http://www.boost.org/libs/utility
  13. #include <boost/utility/result_of.hpp>
  14. #include <utility>
  15. #include <boost/static_assert.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. struct int_result_type
  18. {
  19. typedef int result_type;
  20. result_type operator()(float);
  21. };
  22. struct int_result_of
  23. {
  24. template<typename F> struct result { typedef int type; };
  25. result<int_result_of(double)>::type operator()(double);
  26. result<const int_result_of(double)>::type operator()(double) const;
  27. result<int_result_of()>::type operator()();
  28. result<volatile int_result_of()>::type operator()() volatile;
  29. };
  30. struct int_result_type_and_float_result_of_and_char_return
  31. {
  32. typedef int result_type;
  33. template<typename F> struct result { typedef float type; };
  34. char operator()(char);
  35. };
  36. template<typename T>
  37. struct int_result_type_template
  38. {
  39. typedef int result_type;
  40. result_type operator()(float);
  41. };
  42. template<typename T>
  43. struct int_result_of_template
  44. {
  45. template<typename F> struct result;
  46. template<typename This, typename That> struct result<This(That)> { typedef int type; };
  47. typename result<int_result_of_template<T>(double)>::type operator()(double);
  48. typename result<const int_result_of_template<T>(double)>::type operator()(double) const;
  49. typename result<int_result_of_template<T>(double)>::type operator()();
  50. typename result<volatile int_result_of_template<T>(double)>::type operator()() volatile;
  51. };
  52. template<typename T>
  53. struct int_result_type_and_float_result_of_and_char_return_template
  54. {
  55. typedef int result_type;
  56. template<typename F> struct result;
  57. template<typename This, typename That> struct result<This(That)> { typedef float type; };
  58. char operator()(char);
  59. };
  60. template<typename T>
  61. struct cv_overload_check {};
  62. struct result_of_member_function_template
  63. {
  64. template<typename F> struct result;
  65. template<typename This, typename That> struct result<This(That)> { typedef That type; };
  66. template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
  67. template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
  68. template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
  69. template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
  70. template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
  71. template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
  72. template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
  73. template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
  74. template<class T> typename result<result_of_member_function_template(T &, T)>::type operator()(T &, T);
  75. template<typename This, typename That> struct result<This(That const &, That)> { typedef That const & type; };
  76. template<class T> typename result<result_of_member_function_template(T const &, T)>::type operator()(T const &, T);
  77. template<typename This, typename That> struct result<This(That volatile &, That)> { typedef That volatile & type; };
  78. template<class T> typename result<result_of_member_function_template(T volatile &, T)>::type operator()(T volatile &, T);
  79. template<typename This, typename That> struct result<This(That const volatile &, That)> { typedef That const volatile & type; };
  80. template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
  81. };
  82. struct no_result_type_or_result
  83. {
  84. short operator()(double);
  85. cv_overload_check<const short> operator()(double) const;
  86. cv_overload_check<volatile short> operator()(double) volatile;
  87. cv_overload_check<const volatile short> operator()(double) const volatile;
  88. int operator()();
  89. cv_overload_check<const int> operator()() const;
  90. cv_overload_check<volatile int> operator()() volatile;
  91. cv_overload_check<const volatile int> operator()() const volatile;
  92. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  93. short operator()(int&&);
  94. int operator()(int&);
  95. long operator()(int const&);
  96. #endif
  97. };
  98. template<typename T>
  99. struct no_result_type_or_result_template
  100. {
  101. short operator()(double);
  102. cv_overload_check<const short> operator()(double) const;
  103. cv_overload_check<volatile short> operator()(double) volatile;
  104. cv_overload_check<const volatile short> operator()(double) const volatile;
  105. int operator()();
  106. cv_overload_check<const int> operator()() const;
  107. cv_overload_check<volatile int> operator()() volatile;
  108. cv_overload_check<const volatile int> operator()() const volatile;
  109. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  110. short operator()(int&&);
  111. int operator()(int&);
  112. long operator()(int const&);
  113. #endif
  114. };
  115. // sfinae_tests are derived from example code from Joel de Guzman,
  116. // which demonstrated the interaction between result_of and SFINAE.
  117. template <typename F, typename Arg>
  118. typename boost::result_of<F(Arg const&)>::type
  119. sfinae_test(F f, Arg const& arg)
  120. {
  121. return f(arg);
  122. }
  123. template <typename F, typename Arg>
  124. typename boost::result_of<F(Arg&)>::type
  125. sfinae_test(F f, Arg& arg)
  126. {
  127. return f(arg);
  128. }
  129. int sfinae_test_f(int& i)
  130. {
  131. return i;
  132. }
  133. struct X {};
  134. int main()
  135. {
  136. using namespace boost;
  137. typedef int (*func_ptr)(float, double);
  138. typedef int (&func_ref)(float, double);
  139. typedef int (*func_ptr_0)();
  140. typedef int (&func_ref_0)();
  141. typedef void (*func_ptr_void)(float, double);
  142. typedef void (&func_ref_void)(float, double);
  143. typedef void (*func_ptr_void_0)();
  144. typedef void (&func_ref_void_0)();
  145. typedef int (X::*mem_func_ptr)(float);
  146. typedef int (X::*mem_func_ptr_c)(float) const;
  147. typedef int (X::*mem_func_ptr_v)(float) volatile;
  148. typedef int (X::*mem_func_ptr_cv)(float) const volatile;
  149. typedef int (X::*mem_func_ptr_0)();
  150. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type(float)>::type, int>::value));
  151. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(double)>::type, int>::value));
  152. BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of(double)>::type, int>::value));
  153. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_template<void>(float)>::type, int>::value));
  154. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(double)>::type, int>::value));
  155. BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of_template<void>(double)>::type, int>::value));
  156. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type(float)>::type, int>::value));
  157. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(double)>::type, int>::value));
  158. BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of(double)>::type, int>::value));
  159. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_template<void>(float)>::type, int>::value));
  160. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(double)>::type, int>::value));
  161. BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of_template<void>(double)>::type, int>::value));
  162. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(void)>::type, void>::value));
  163. BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of(void)>::type, void>::value));
  164. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(void)>::type, void>::value));
  165. BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
  166. // Prior to decltype, result_of could not deduce the return type
  167. // of nullary function objects unless they exposed a result_type.
  168. #if defined(BOOST_RESULT_OF_USE_DECLTYPE)
  169. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value));
  170. BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
  171. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
  172. BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, int>::value));
  173. #else
  174. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, void>::value));
  175. BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, void>::value));
  176. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, void>::value));
  177. BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
  178. #endif
  179. // Prior to decltype, result_of ignored a nested result<> if
  180. // result_type was defined. After decltype, result_of deduces the
  181. // actual return type of the function object, ignoring both
  182. // result<> and result_type.
  183. #if defined(BOOST_RESULT_OF_USE_DECLTYPE)
  184. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
  185. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
  186. #else
  187. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
  188. BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
  189. #endif
  190. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
  191. BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
  192. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
  193. BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
  194. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value));
  195. BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value));
  196. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
  197. BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
  198. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value));
  199. BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value));
  200. BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
  201. BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
  202. BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
  203. BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
  204. BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value));
  205. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
  206. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
  207. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value));
  208. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value));
  209. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
  210. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
  211. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value));
  212. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value));
  213. BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
  214. BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
  215. BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
  216. BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
  217. BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value));
  218. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
  219. BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value));
  220. BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
  221. BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
  222. BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
  223. BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
  224. BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
  225. BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
  226. BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
  227. BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
  228. BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
  229. BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
  230. BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
  231. BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
  232. BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
  233. BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
  234. BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
  235. BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
  236. typedef int (*pf_t)(int);
  237. BOOST_STATIC_ASSERT((is_same<result_of<pf_t(int)>::type, int>::value));
  238. BOOST_STATIC_ASSERT((is_same<result_of<pf_t const(int)>::type,int>::value));
  239. BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value));
  240. BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::type,int>::value));
  241. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
  242. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value));
  243. BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
  244. BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
  245. BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
  246. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
  247. BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
  248. BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
  249. BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
  250. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
  251. BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
  252. BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
  253. 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));
  254. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
  255. BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
  256. BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
  257. 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));
  258. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr&(char, float)>::type, int>::value));
  259. BOOST_STATIC_ASSERT((is_same<result_of<func_ptr const&(char, float)>::type, int>::value));
  260. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of&(double)>::type, int>::value));
  261. BOOST_STATIC_ASSERT((is_same<result_of<int_result_of const&(double)>::type, int>::value));
  262. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  263. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
  264. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
  265. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
  266. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
  267. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
  268. BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
  269. #endif
  270. #endif
  271. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
  272. int i = 123;
  273. sfinae_test(sfinae_test_f, i);
  274. #endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
  275. return 0;
  276. }