1 // Boost.TypeErasure library 2 // 3 // Copyright 2012 Steven Watanabe 4 // 5 // Distributed under the Boost Software License Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // $Id$ 10 11 #if !defined(BOOST_PP_IS_ITERATING) 12 13 #ifndef BOOST_TYPE_ERASURE_DETAIL_CHECK_CALL_HPP_INCLUDED 14 #define BOOST_TYPE_ERASURE_DETAIL_CHECK_CALL_HPP_INCLUDED 15 16 #include <boost/mpl/eval_if.hpp> 17 #include <boost/mpl/bool.hpp> 18 #include <boost/mpl/and.hpp> 19 #include <boost/type_traits/is_convertible.hpp> 20 #include <boost/type_traits/remove_reference.hpp> 21 #include <boost/type_traits/remove_cv.hpp> 22 #include <boost/type_traits/is_reference.hpp> 23 #include <boost/type_traits/is_const.hpp> 24 #include <boost/type_traits/function_traits.hpp> 25 #include <boost/preprocessor/iteration/iterate.hpp> 26 #include <boost/preprocessor/repetition/enum_params.hpp> 27 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 28 #include <boost/preprocessor/repetition/repeat.hpp> 29 #include <boost/preprocessor/cat.hpp> 30 #include <boost/type_erasure/placeholder_of.hpp> 31 32 namespace boost { 33 namespace type_erasure { 34 namespace detail { 35 36 template<class Sig, class Args> 37 struct check_call : ::boost::mpl::false_ {}; 38 39 template<class T, class Enable = void> 40 struct qualified_placeholder 41 { 42 typedef void type; 43 }; 44 45 template<class T> 46 struct qualified_placeholder<T&, typename T::_boost_type_erasure_is_any> 47 { 48 typedef typename ::boost::type_erasure::placeholder_of<T>::type placeholder; 49 typedef typename ::boost::remove_reference<placeholder>::type unref; 50 typedef typename ::boost::mpl::if_< ::boost::is_const<T>, 51 const unref, 52 unref 53 >::type add_const; 54 typedef typename ::boost::mpl::if_< ::boost::is_reference<placeholder>, 55 placeholder, 56 add_const& 57 >::type type; 58 }; 59 60 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 61 62 template<class T> 63 struct qualified_placeholder<T&&, typename T::_boost_type_erasure_is_any> 64 { 65 typedef typename ::boost::type_erasure::placeholder_of<T>::type placeholder; 66 typedef placeholder&& type; 67 }; 68 69 #endif 70 71 template<class P, class A> 72 struct check_placeholder_arg_impl : ::boost::mpl::false_ {}; 73 74 template<class P> 75 struct check_placeholder_arg_impl<P, P&> : ::boost::mpl::true_ {}; 76 77 template<class P> 78 struct check_placeholder_arg_impl<P, const P&> : ::boost::mpl::true_ {}; 79 80 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 81 82 template<class P> 83 struct check_placeholder_arg_impl<P, P&&> : ::boost::mpl::true_ {}; 84 85 #endif 86 87 template<class P> 88 struct check_placeholder_arg_impl<P&, P&> : ::boost::mpl::true_ {}; 89 90 template<class P> 91 struct check_placeholder_arg_impl<const P&, P&> : ::boost::mpl::true_ {}; 92 93 template<class P> 94 struct check_placeholder_arg_impl<const P&, const P&> : ::boost::mpl::true_ {}; 95 96 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 97 98 template<class P> 99 struct check_placeholder_arg_impl<const P&, P&&> : ::boost::mpl::true_ {}; 100 101 template<class P> 102 struct check_placeholder_arg_impl<P&&, P&&> : ::boost::mpl::true_ {}; 103 104 #endif 105 106 template<class P, class Arg> 107 struct check_placeholder_arg : 108 check_placeholder_arg_impl< 109 P, 110 typename ::boost::type_erasure::detail::qualified_placeholder<Arg>::type 111 >::type 112 {}; 113 114 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ 115 ((defined(__GNUC__) && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))) || \ 116 defined(__MINGW32__) || defined(__MINGW64__)) 117 #define BOOST_TYPE_ERASURE_BROKEN_RVALUE_IS_CONVERTIBLE 118 #endif 119 120 template<class FormalArg, class ActualArg> 121 struct check_arg 122 { 123 typedef typename ::boost::mpl::eval_if< 124 is_placeholder< 125 typename ::boost::remove_cv< 126 typename ::boost::remove_reference<FormalArg>::type 127 >::type 128 >, 129 ::boost::type_erasure::detail::check_placeholder_arg<FormalArg, ActualArg>, 130 #ifdef BOOST_TYPE_ERASURE_BROKEN_RVALUE_IS_CONVERTIBLE 131 ::boost::mpl::true_ 132 #else 133 ::boost::is_convertible<ActualArg, FormalArg> 134 #endif 135 >::type type; 136 }; 137 138 #define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/check_call.hpp> 139 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) 140 #include BOOST_PP_ITERATE() 141 142 } 143 } 144 } 145 146 #endif 147 148 #else 149 150 #define N BOOST_PP_ITERATION() 151 152 #define BOOST_TYPE_ERASURE_CHECK_ARG(z, n, data) \ 153 typedef typename ::boost::type_erasure::detail::check_arg< \ 154 BOOST_PP_CAT(T, n), \ 155 BOOST_PP_CAT(U, n) \ 156 >::type BOOST_PP_CAT(check, n); \ 157 typedef typename ::boost::mpl::and_< \ 158 BOOST_PP_CAT(type, n), \ 159 BOOST_PP_CAT(check, n) \ 160 >::type BOOST_PP_CAT(type, BOOST_PP_INC(n)); 161 162 template< 163 class R 164 BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) 165 BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) 166 > 167 struct check_call<R(BOOST_PP_ENUM_PARAMS(N, T)), void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, u))> { 168 typedef ::boost::mpl::true_ type0; 169 BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CHECK_ARG, ~) 170 typedef BOOST_PP_CAT(type, N) type; 171 }; 172 173 #undef N 174 175 #endif 176