• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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