1 2 // Copyright (C) 2009-2012 Lorenzo Caminiti 3 // Distributed under the Boost Software License, Version 1.0 4 // (see accompanying file LICENSE_1_0.txt or a copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 // Home at http://www.boost.org/libs/local_function 7 8 #ifndef BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_HPP_ 9 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_HPP_ 10 11 #include <boost/local_function/aux_/symbol.hpp> 12 #include <boost/local_function/aux_/preprocessor/traits/decl_returns.hpp> 13 #include <boost/scope_exit.hpp> 14 #include <boost/typeof/typeof.hpp> 15 #include <boost/type_traits/remove_pointer.hpp> 16 #include <boost/type_traits/function_traits.hpp> 17 #include <boost/preprocessor/control/iif.hpp> 18 #include <boost/preprocessor/control/expr_iif.hpp> 19 #include <boost/preprocessor/list/adt.hpp> 20 #include <boost/preprocessor/cat.hpp> 21 22 // PRIVATE // 23 24 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id) \ 25 /* symbol (not internal) also gives error if missing result type */ \ 26 BOOST_PP_CAT( \ 27 ERROR_missing_result_type_before_the_local_function_parameter_macro_id, \ 28 id) 29 30 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) \ 31 BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_params)(id) ) 32 33 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ 34 BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (result_type)(id) ) 35 36 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_ \ 37 /* this does not have to be an integral index because ScopeExit uses */ \ 38 /* just as a symbol to concatenate go generate unique symbols (but */ \ 39 /* if it'd ever needed to became integral, the number of function */ \ 40 /* params + 1 as in the macro CONFIG_ARITY_MAX could be used) */ \ 41 result 42 43 // User did not explicitly specified result type, deduce it (using Typeof). 44 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DEDUCE_( \ 45 id, typename01, decl_traits) \ 46 /* user specified result type here */ \ 47 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DECL(id) \ 48 /* tagging, wrapping, etc as from ScopeExit type deduction are */ \ 49 /* necessary within templates (at least on GCC) to work around an */ \ 50 /* compiler internal errors) */ \ 51 BOOST_SCOPE_EXIT_DETAIL_TAG_DECL(0, /* no recursive step r */ \ 52 id, BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ 53 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ 54 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(0, /* no recursive step r */ \ 55 ( id, BOOST_PP_EXPR_IIF(typename01, typename) ), \ 56 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ 57 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ 58 /* extra struct to workaround GCC and other compiler's issues */ \ 59 struct BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) { \ 60 typedef \ 61 BOOST_PP_EXPR_IIF(typename01, typename) \ 62 ::boost::function_traits< \ 63 BOOST_PP_EXPR_IIF(typename01, typename) \ 64 ::boost::remove_pointer< \ 65 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(id, \ 66 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ 67 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ 68 >::type \ 69 >::result_type \ 70 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ 71 ; \ 72 }; 73 74 // Use result type as explicitly specified by user (no type deduction needed). 75 // Precondition: RETURNS(decl_traits) != NIL 76 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPED_( \ 77 id, typename01, decl_traits) \ 78 /* user specified result type here */ \ 79 struct BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) { \ 80 typedef \ 81 BOOST_PP_LIST_FIRST( \ 82 BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_RETURNS( \ 83 decl_traits)) \ 84 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ 85 ; \ 86 }; 87 88 // PUBLIC // 89 90 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ 91 BOOST_PP_EXPR_IIF(typename01, typename) \ 92 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) :: \ 93 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) 94 95 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DECL(id) \ 96 /* result type here */ (*BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id))(); 97 98 #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT(id, typename01, decl_traits) \ 99 BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS( \ 100 BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_RETURNS(decl_traits)), \ 101 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPED_ \ 102 , \ 103 BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DEDUCE_ \ 104 )(id, typename01, decl_traits) 105 106 #endif // #include guard 107 108