// Boost result_of library // Copyright Douglas Gregor 2003-2004. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Examples: // To run the default test: // $ cd libs/utility/test && bjam // To test decltype on g++ 2.7: // $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE" #include // For more information, see http://www.boost.org/libs/utility #include #include #include #include struct int_result_type { typedef int result_type; result_type operator()(float); }; struct int_result_of { template struct result { typedef int type; }; result::type operator()(double); result::type operator()(double) const; result::type operator()(); result::type operator()() volatile; }; struct int_result_type_and_float_result_of_and_char_return { typedef int result_type; template struct result { typedef float type; }; char operator()(char); }; template struct int_result_type_template { typedef int result_type; result_type operator()(float); }; template struct int_result_of_template { template struct result; template struct result { typedef int type; }; typename result(double)>::type operator()(double); typename result(double)>::type operator()(double) const; typename result(double)>::type operator()(); typename result(double)>::type operator()() volatile; }; template struct int_result_type_and_float_result_of_and_char_return_template { typedef int result_type; template struct result; template struct result { typedef float type; }; char operator()(char); }; template struct cv_overload_check {}; struct result_of_member_function_template { template struct result; template struct result { typedef That type; }; template typename result::type operator()(T); template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) const; template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) volatile; template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) const volatile; template struct result { typedef That & type; }; template typename result::type operator()(T &, T); template struct result { typedef That const & type; }; template typename result::type operator()(T const &, T); template struct result { typedef That volatile & type; }; template typename result::type operator()(T volatile &, T); template struct result { typedef That const volatile & type; }; template typename result::type operator()(T const volatile &, T); }; struct no_result_type_or_result { short operator()(double); cv_overload_check operator()(double) const; cv_overload_check operator()(double) volatile; cv_overload_check operator()(double) const volatile; int operator()(); cv_overload_check operator()() const; cv_overload_check operator()() volatile; cv_overload_check operator()() const volatile; #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); long operator()(int const&); #endif }; template struct no_result_type_or_result_template { short operator()(double); cv_overload_check operator()(double) const; cv_overload_check operator()(double) volatile; cv_overload_check operator()(double) const volatile; int operator()(); cv_overload_check operator()() const; cv_overload_check operator()() volatile; cv_overload_check operator()() const volatile; #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); long operator()(int const&); #endif }; // sfinae_tests are derived from example code from Joel de Guzman, // which demonstrated the interaction between result_of and SFINAE. template typename boost::result_of::type sfinae_test(F f, Arg const& arg) { return f(arg); } template typename boost::result_of::type sfinae_test(F f, Arg& arg) { return f(arg); } int sfinae_test_f(int& i) { return i; } struct X {}; int main() { using namespace boost; typedef int (*func_ptr)(float, double); typedef int (&func_ref)(float, double); typedef int (*func_ptr_0)(); typedef int (&func_ref_0)(); typedef void (*func_ptr_void)(float, double); typedef void (&func_ref_void)(float, double); typedef void (*func_ptr_void_0)(); typedef void (&func_ref_void_0)(); typedef int (X::*mem_func_ptr)(float); typedef int (X::*mem_func_ptr_c)(float) const; typedef int (X::*mem_func_ptr_v)(float) volatile; typedef int (X::*mem_func_ptr_cv)(float) const volatile; typedef int (X::*mem_func_ptr_0)(); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(float)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(float)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); // Prior to decltype, result_of could not deduce the return type // of nullary function objects unless they exposed a result_type. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); #else BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); #endif // Prior to decltype, result_of ignored a nested result<> if // result_type was defined. After decltype, result_of deduces the // actual return type of the function object, ignoring both // result<> and result_type. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, char>::value)); BOOST_STATIC_ASSERT((is_same(char)>::type, char>::value)); #else BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); #endif BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, double>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, double>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); typedef int (*pf_t)(int); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type,int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type,int>::value)); #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) BOOST_STATIC_ASSERT((is_same::type, short>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_STATIC_ASSERT((is_same::type, short>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, long>::value)); BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value)); BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value)); BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value)); #endif #endif #if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) int i = 123; sfinae_test(sfinae_test_f, i); #endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) return 0; }