1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   function_traits.hpp
9  * \author Andrey Semashev
10  * \date   30.08.2009
11  *
12  * \brief  This header is the Boost.Log library implementation, see the library documentation
13  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14  */
15 
16 #ifndef BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
17 #define BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
18 
19 #include <boost/mpl/has_xxx.hpp>
20 #include <boost/log/detail/config.hpp>
21 
22 #if defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX)
23 #   if !defined(BOOST_LOG_NO_FUNCTION_TRAITS)
24 #      define BOOST_LOG_NO_FUNCTION_TRAITS
25 #   endif
26 #else
27 
28 #include <boost/mpl/int.hpp>
29 #include <boost/mpl/front.hpp>
30 #include <boost/mpl/pop_front.hpp>
31 #include <boost/type_traits/remove_cv.hpp>
32 #include <boost/type_traits/remove_reference.hpp>
33 #include <boost/function_types/function_arity.hpp>
34 #include <boost/function_types/parameter_types.hpp>
35 #include <boost/function_types/is_nonmember_callable_builtin.hpp>
36 #include <boost/log/detail/header.hpp>
37 
38 #ifdef BOOST_HAS_PRAGMA_ONCE
39 #pragma once
40 #endif
41 
42 namespace boost {
43 
44 BOOST_LOG_OPEN_NAMESPACE
45 
46 namespace aux {
47 
48     //  A number of traits to deal with functors
49     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_argument_type, argument_type, false)
50     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_first_argument_type, first_argument_type, false)
51     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_second_argument_type, second_argument_type, false)
52     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg1_type, arg1_type, false)
53     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg2_type, arg2_type, false)
54 
55     namespace has_arity_no_adl {
56 
57         typedef char yes_type;
58         struct no_type
59         {
60             char dummy[2];
61         };
62 
63         template< typename FunT, int ArityV = FunT::arity >
64         struct checker
65         {
66         };
67 
68         template< typename FunT >
69         yes_type has_arity_impl(FunT const&, checker< FunT >*);
70         template< typename FunT >
71         no_type has_arity_impl(FunT const&, ...);
72 
73     } // namespace has_arity_no_adl
74 
75     //! The metafunction detects if the type has an arity static constant member
76     template< typename FunT >
77     struct has_arity
78     {
79         static FunT const& get_FunT();
80 
81         enum value_t { value = (sizeof(has_arity_no_adl::has_arity_impl(get_FunT(), 0)) == sizeof(has_arity_no_adl::yes_type)) };
82         typedef mpl::bool_< value > type;
83     };
84 
85     //! The metafunction results in an unqualified type with removed reference
86     template< typename T >
87     struct root_type :
88         public remove_cv<
89             typename remove_reference<
90                 T
91             >::type
92         >
93     {
94     };
95 
96     template<
97         typename FunT,
98         bool = function_types::is_nonmember_callable_builtin< FunT >::value,
99         bool = has_argument_type< FunT >::value,
100         bool = has_first_argument_type< FunT >::value,
101         bool = has_arg1_type< FunT >::value
102     >
103     struct first_argument_type_of_impl
104     {
105     };
106     template< typename FunT >
107     struct first_argument_type_of_impl< FunT, true, false, false, false >
108     {
109         typedef typename root_type<
110             typename mpl::front<
111                 typename function_types::parameter_types< FunT >::type
112             >::type
113         >::type type;
114     };
115     template< typename FunT, bool HasFirstArgumentV, bool HasArg1V >
116     struct first_argument_type_of_impl< FunT, false, true, HasFirstArgumentV, HasArg1V >
117     {
118         typedef typename root_type<
119             typename FunT::argument_type
120         >::type type;
121     };
122     template< typename FunT, bool HasArg1V >
123     struct first_argument_type_of_impl< FunT, false, false, true, HasArg1V >
124     {
125         typedef typename root_type<
126             typename FunT::first_argument_type
127         >::type type;
128     };
129     template< typename FunT >
130     struct first_argument_type_of_impl< FunT, false, false, false, true >
131     {
132         typedef typename root_type<
133             typename FunT::arg1_type
134         >::type type;
135     };
136 
137     //! The metafunction returns the first argument type of a function
138     template< typename FunT >
139     struct first_argument_type_of :
140         public first_argument_type_of_impl< FunT >
141     {
142     };
143 
144 
145     template<
146         typename FunT,
147         bool = function_types::is_nonmember_callable_builtin< FunT >::value,
148         bool = has_second_argument_type< FunT >::value,
149         bool = has_arg2_type< FunT >::value
150     >
151     struct second_argument_type_of_impl
152     {
153     };
154     template< typename FunT >
155     struct second_argument_type_of_impl< FunT, true, false, false >
156     {
157         typedef typename root_type<
158             typename mpl::front<
159                 typename mpl::pop_front<
160                     typename function_types::parameter_types< FunT >::type
161                 >::type
162             >::type
163         >::type type;
164     };
165     template< typename FunT, bool HasArg2V >
166     struct second_argument_type_of_impl< FunT, false, true, HasArg2V >
167     {
168         typedef typename root_type<
169             typename FunT::second_argument_type
170         >::type type;
171     };
172     template< typename FunT >
173     struct second_argument_type_of_impl< FunT, false, false, true >
174     {
175         typedef typename root_type<
176             typename FunT::arg2_type
177         >::type type;
178     };
179 
180     //! The metafunction returns the second argument type of a function
181     template< typename FunT >
182     struct second_argument_type_of :
183         public second_argument_type_of_impl< FunT >
184     {
185     };
186 
187 
188     template<
189         typename FunT,
190         bool = function_types::is_nonmember_callable_builtin< FunT >::value,
191         bool = has_arity< FunT >::value,
192         bool = has_argument_type< FunT >::value,
193         bool = has_second_argument_type< FunT >::value
194     >
195     struct arity_of_impl
196     {
197     };
198     template< typename FunT >
199     struct arity_of_impl< FunT, true, false, false, false > :
200         public function_types::function_arity< FunT >
201     {
202     };
203     template< typename FunT, bool HasArgumentTypeV, bool HasSecondArgumentTypeV >
204     struct arity_of_impl< FunT, false, true, HasArgumentTypeV, HasSecondArgumentTypeV > :
205         public mpl::int_< FunT::arity >
206     {
207     };
208     template< typename FunT, bool HasArgumentTypeV >
209     struct arity_of_impl< FunT, false, false, HasArgumentTypeV, true > :
210         public mpl::int_< 2 >
211     {
212     };
213     template< typename FunT >
214     struct arity_of_impl< FunT, false, false, true, false > :
215         public mpl::int_< 1 >
216     {
217     };
218 
219     //! The metafunction returns the arity of a function
220     template< typename FunT >
221     struct arity_of :
222         public arity_of_impl< FunT >
223     {
224     };
225 
226 } // namespace aux
227 
228 BOOST_LOG_CLOSE_NAMESPACE // namespace log
229 
230 } // namespace boost
231 
232 #include <boost/log/detail/footer.hpp>
233 
234 #endif // defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX)
235 
236 #endif // BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
237