1 // Copyright Cromwell D. Enage 2018. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_PARAMETER_AUGMENT_PREDICATE_HPP 7 #define BOOST_PARAMETER_AUGMENT_PREDICATE_HPP 8 9 #include <boost/parameter/keyword_fwd.hpp> 10 #include <boost/mpl/bool.hpp> 11 #include <boost/mpl/if.hpp> 12 #include <boost/mpl/eval_if.hpp> 13 #include <boost/type_traits/is_lvalue_reference.hpp> 14 #include <boost/type_traits/is_scalar.hpp> 15 #include <boost/type_traits/is_same.hpp> 16 17 namespace boost { namespace parameter { namespace aux { 18 19 template <typename V, typename R, typename Tag> 20 struct augment_predicate_check_consume_ref 21 : ::boost::mpl::eval_if< 22 ::boost::is_scalar<V> 23 , ::boost::mpl::true_ 24 , ::boost::mpl::eval_if< 25 ::boost::is_same< 26 typename Tag::qualifier 27 , ::boost::parameter::consume_reference 28 > 29 , ::boost::mpl::if_< 30 ::boost::is_lvalue_reference<R> 31 , ::boost::mpl::false_ 32 , ::boost::mpl::true_ 33 > 34 , boost::mpl::true_ 35 > 36 >::type 37 { 38 }; 39 }}} // namespace boost::parameter::aux 40 41 #include <boost/type_traits/is_const.hpp> 42 43 namespace boost { namespace parameter { namespace aux { 44 45 template <typename V, typename R, typename Tag> 46 struct augment_predicate_check_out_ref 47 : ::boost::mpl::eval_if< 48 ::boost::is_same< 49 typename Tag::qualifier 50 , ::boost::parameter::out_reference 51 > 52 , ::boost::mpl::eval_if< 53 ::boost::is_lvalue_reference<R> 54 , ::boost::mpl::if_< 55 ::boost::is_const<V> 56 , ::boost::mpl::false_ 57 , ::boost::mpl::true_ 58 > 59 , ::boost::mpl::false_ 60 > 61 , ::boost::mpl::true_ 62 >::type 63 { 64 }; 65 }}} // namespace boost::parameter::aux 66 67 #include <boost/parameter/aux_/lambda_tag.hpp> 68 #include <boost/mpl/apply_wrap.hpp> 69 #include <boost/mpl/lambda.hpp> 70 71 namespace boost { namespace parameter { namespace aux { 72 73 template < 74 typename Predicate 75 , typename R 76 , typename Tag 77 , typename T 78 , typename Args 79 > 80 class augment_predicate 81 { 82 typedef typename ::boost::mpl::lambda< 83 Predicate 84 , ::boost::parameter::aux::lambda_tag 85 >::type _actual_predicate; 86 87 public: 88 typedef typename ::boost::mpl::eval_if< 89 typename ::boost::mpl::if_< 90 ::boost::parameter::aux 91 ::augment_predicate_check_consume_ref<T,R,Tag> 92 , ::boost::parameter::aux 93 ::augment_predicate_check_out_ref<T,R,Tag> 94 , ::boost::mpl::false_ 95 >::type 96 , ::boost::mpl::apply_wrap2<_actual_predicate,T,Args> 97 , ::boost::mpl::false_ 98 >::type type; 99 }; 100 }}} // namespace boost::parameter::aux 101 102 #include <boost/parameter/config.hpp> 103 104 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 105 #include <boost/mp11/integral.hpp> 106 #include <boost/mp11/utility.hpp> 107 #include <type_traits> 108 109 namespace boost { namespace parameter { namespace aux { 110 111 template <typename V, typename R, typename Tag> 112 using augment_predicate_check_consume_ref_mp11 = ::boost::mp11::mp_if< 113 ::std::is_scalar<V> 114 , ::boost::mp11::mp_true 115 , ::boost::mp11::mp_if< 116 ::std::is_same< 117 typename Tag::qualifier 118 , ::boost::parameter::consume_reference 119 > 120 , ::boost::mp11::mp_if< 121 ::std::is_lvalue_reference<R> 122 , ::boost::mp11::mp_false 123 , ::boost::mp11::mp_true 124 > 125 , boost::mp11::mp_true 126 > 127 >; 128 129 template <typename V, typename R, typename Tag> 130 using augment_predicate_check_out_ref_mp11 = ::boost::mp11::mp_if< 131 ::std::is_same< 132 typename Tag::qualifier 133 , ::boost::parameter::out_reference 134 > 135 , ::boost::mp11::mp_if< 136 ::std::is_lvalue_reference<R> 137 , ::boost::mp11::mp_if< 138 ::std::is_const<V> 139 , ::boost::mp11::mp_false 140 , ::boost::mp11::mp_true 141 > 142 , ::boost::mp11::mp_false 143 > 144 , ::boost::mp11::mp_true 145 >; 146 }}} // namespace boost::parameter::aux 147 148 #include <boost/mp11/list.hpp> 149 150 namespace boost { namespace parameter { namespace aux { 151 152 template < 153 typename Predicate 154 , typename R 155 , typename Tag 156 , typename T 157 , typename Args 158 > 159 struct augment_predicate_mp11_impl 160 { 161 using type = ::boost::mp11::mp_if< 162 ::boost::mp11::mp_if< 163 ::boost::parameter::aux 164 ::augment_predicate_check_consume_ref_mp11<T,R,Tag> 165 , ::boost::parameter::aux 166 ::augment_predicate_check_out_ref_mp11<T,R,Tag> 167 , ::boost::mp11::mp_false 168 > 169 , ::boost::mp11 170 ::mp_apply_q<Predicate,::boost::mp11::mp_list<T,Args> > 171 , ::boost::mp11::mp_false 172 >; 173 }; 174 }}} // namespace boost::parameter::aux 175 176 #include <boost/parameter/aux_/has_nested_template_fn.hpp> 177 178 namespace boost { namespace parameter { namespace aux { 179 180 template < 181 typename Predicate 182 , typename R 183 , typename Tag 184 , typename T 185 , typename Args 186 > 187 using augment_predicate_mp11 = ::boost::mp11::mp_if< 188 ::boost::parameter::aux::has_nested_template_fn<Predicate> 189 , ::boost::parameter::aux 190 ::augment_predicate_mp11_impl<Predicate,R,Tag,T,Args> 191 , ::boost::parameter::aux 192 ::augment_predicate<Predicate,R,Tag,T,Args> 193 >; 194 }}} // namespace boost::parameter::aux 195 196 #endif // BOOST_PARAMETER_CAN_USE_MP11 197 #endif // include guard 198 199