1 
2 #ifndef BOOST_CONTRACT_DETAIL_MIRROR_HPP_
3 #define BOOST_CONTRACT_DETAIL_MIRROR_HPP_
4 
5 // Copyright (C) 2008-2018 Lorenzo Caminiti
6 // Distributed under the Boost Software License, Version 1.0 (see accompanying
7 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
8 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
9 
10 #include <boost/contract/detail/name.hpp>
11 #include <boost/function_types/member_function_pointer.hpp>
12 #include <boost/function_types/function_pointer.hpp>
13 #include <boost/function_types/property_tags.hpp>
14 #include <boost/mpl/push_front.hpp>
15 #include <boost/mpl/bool.hpp>
16 #include <boost/preprocessor/control/iif.hpp>
17 #include <boost/preprocessor/tuple/rem.hpp>
18 #include <boost/preprocessor/tuple/eat.hpp>
19 
20 // NOTE: Unfortunately, it is not possible to use Boost.TTI because it not
21 // always works on MSVC (e.g., when the mirror meta-function is invoked
22 // multiple times, MSVC 2010 gives an internal compiler error). This is a
23 // simpler mirror implementation that seems to work better on MSVC.
24 
25 /* PRIVATE */
26 
27 #define BOOST_CONTRACT_DETAIL_MIRROR_END_(tparam) \
28         template<typename> \
29         static boost::contract::detail::mirror::no& apply(...); \
30     public: \
31         static bool const value = sizeof(apply<tparam>(0)) == \
32                 sizeof(boost::contract::detail::mirror::yes); \
33         typedef boost::mpl::bool_<value> type;
34 
35 #define BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION_(is_static, \
36         trait, func_name) \
37     template< \
38         typename BOOST_CONTRACT_DETAIL_NAME1(T), \
39         typename BOOST_CONTRACT_DETAIL_NAME1(R), \
40         class BOOST_CONTRACT_DETAIL_NAME1(P), \
41         class BOOST_CONTRACT_DETAIL_NAME1(G) = boost::function_types::null_tag \
42     > \
43     class trait { \
44         template<class BOOST_CONTRACT_DETAIL_NAME1(C)> \
45         static boost::contract::detail::mirror::yes& apply( \
46             boost::contract::detail::mirror::check_function< \
47                 typename \
48                     BOOST_PP_IIF(is_static, \
49                         boost::function_types::function_pointer \
50                     , \
51                         boost::function_types::member_function_pointer \
52                     ) \
53                 < \
54                     typename boost::mpl::push_front< \
55                         BOOST_PP_IIF(is_static, \
56                             BOOST_CONTRACT_DETAIL_NAME1(P) \
57                             BOOST_PP_TUPLE_EAT(2) \
58                         , \
59                             BOOST_PP_TUPLE_REM(2) \
60                         )( \
61                             typename boost::mpl::push_front< \
62                                 BOOST_CONTRACT_DETAIL_NAME1(P), \
63                                 BOOST_CONTRACT_DETAIL_NAME1(C) \
64                             >::type \
65                         ) \
66                         , BOOST_CONTRACT_DETAIL_NAME1(R) \
67                     >::type, \
68                     BOOST_CONTRACT_DETAIL_NAME1(G) \
69                 >::type, \
70                 &BOOST_CONTRACT_DETAIL_NAME1(C)::func_name \
71             >* \
72         ); \
73         BOOST_CONTRACT_DETAIL_MIRROR_END_( \
74                 BOOST_CONTRACT_DETAIL_NAME1(T)) \
75     };
76 
77 /* PUBLIC */
78 
79 #define BOOST_CONTRACT_DETAIL_MIRROR_HAS_TYPE(trait, type_name)\
80     template<typename BOOST_CONTRACT_DETAIL_NAME1(T)> \
81     class trait { \
82         template<class BOOST_CONTRACT_DETAIL_NAME1(C)> \
83         static boost::contract::detail::mirror::yes& apply( \
84                 typename BOOST_CONTRACT_DETAIL_NAME1(C)::type_name*); \
85         BOOST_CONTRACT_DETAIL_MIRROR_END_( \
86                 BOOST_CONTRACT_DETAIL_NAME1(T)) \
87     };
88 
89 #define BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION( \
90         trait, func_name) \
91     BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION_( \
92             /* is_static = */ 0, trait, func_name)
93 
94 #define BOOST_CONTRACT_DETAIL_MIRROR_HAS_STATIC_MEMBER_FUNCTION(trait, \
95         func_name) \
96     BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION_( \
97             /* is_static = */ 1, trait, func_name)
98 
99 /* CODE */
100 
101 namespace boost { namespace contract { namespace detail { namespace mirror {
102 
103 typedef class {} yes;
104 typedef yes no[2];
105 
106 template<typename F, F> class check_function;
107 
108 } } } } // namespace
109 
110 #endif // #include guard
111 
112