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 | |