]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Defines macros to perform different kinds of assertions. | |
4 | ||
5 | @copyright Louis Dionne 2013-2016 | |
6 | Distributed under the Boost Software License, Version 1.0. | |
7 | (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | |
8 | */ | |
9 | ||
10 | #ifndef BOOST_HANA_ASSERT_HPP | |
11 | #define BOOST_HANA_ASSERT_HPP | |
12 | ||
13 | #include <boost/hana/concept/constant.hpp> | |
14 | #include <boost/hana/config.hpp> | |
15 | #include <boost/hana/detail/preprocessor.hpp> | |
16 | #include <boost/hana/if.hpp> | |
17 | #include <boost/hana/value.hpp> | |
18 | ||
19 | #include <cstdio> | |
20 | #include <cstdlib> | |
21 | ||
22 | ||
23 | #if defined(BOOST_HANA_DOXYGEN_INVOKED) | |
24 | //! @ingroup group-assertions | |
25 | //! Expands to a runtime assertion. | |
26 | //! | |
27 | //! Given a condition known at runtime, this macro expands to a runtime | |
28 | //! assertion similar to the `assert` macro. The provided condition must | |
29 | //! be explicitly convertible to a `bool`, and it must not be a model of | |
30 | //! the `Constant` concept. If the condition is a `Constant`, a static | |
31 | //! assertion will be triggered, asking you to use the | |
32 | //! `BOOST_HANA_CONSTANT_ASSERT` macro instead. | |
33 | //! | |
34 | //! @note | |
35 | //! This macro may only be used at function scope. | |
36 | # define BOOST_HANA_RUNTIME_ASSERT(condition) unspecified | |
37 | ||
38 | //! @ingroup group-assertions | |
39 | //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but allows providing a | |
40 | //! custom failure message. | |
41 | //! | |
42 | //! @warning | |
43 | //! Conditions that contain multiple comma-separated elements should be | |
44 | //! parenthesized. | |
45 | # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) unspecified | |
46 | ||
47 | //! @ingroup group-assertions | |
48 | //! Compile-time assertion for `Constant`s. | |
49 | //! | |
50 | //! Given a condition known at compile-time in the form of a `Constant`, | |
51 | //! this macro expands to a compile-time assertion similar to a `static_assert`. | |
52 | //! The provided condition must be a model of the `Constant` concept, in | |
53 | //! which case its value is retrieved using `hana::value` and then converted | |
54 | //! to a `bool`. If the condition is not a `Constant`, a static assertion | |
55 | //! will be triggered, asking you to use the `BOOST_HANA_RUNTIME_ASSERT` | |
56 | //! macro instead. | |
57 | //! | |
58 | //! This macro may be used at global/namespace scope and function scope | |
59 | //! only; it may not be used at class scope. Note that the condition may | |
60 | //! never be evaluated at runtime. Hence, any side effect may not take | |
61 | //! place (but you shouldn't rely on side effects inside assertions anyway). | |
62 | # define BOOST_HANA_CONSTANT_ASSERT(condition) unspecified | |
63 | ||
64 | //! @ingroup group-assertions | |
65 | //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but allows providing a | |
66 | //! custom failure message. | |
67 | //! | |
68 | //! @warning | |
69 | //! Conditions that contain multiple comma-separated elements should be | |
70 | //! parenthesized. | |
71 | # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) unspecified | |
72 | ||
73 | //! @ingroup group-assertions | |
74 | //! Expands to the strongest form of assertion possible for the given | |
75 | //! condition. | |
76 | //! | |
77 | //! Given a condition, `BOOST_HANA_ASSERT` expands either to a compile-time | |
78 | //! or to a runtime assertion, depending on whether the value of the | |
79 | //! condition is known at compile-time or at runtime. Compile-time | |
80 | //! assertions are always preferred over runtime assertions. If the | |
81 | //! condition is a model of the `Constant` concept, its value (retrievable | |
82 | //! with `hana::value`) is assumed to be explicitly convertible to `bool`, | |
83 | //! and a compile-time assertion is performed on it. Otherwise, the | |
84 | //! condition itself is assumed to be explicitly convertible to `bool`, | |
85 | //! and a runtime assertion is performed on it. | |
86 | //! | |
87 | //! If the assertion can be carried out at compile-time, the condition | |
88 | //! is not guaranteed to be evaluated at runtime at all (but it may). | |
89 | //! Hence, in general, you shouldn't rely on side effects that take place | |
90 | //! inside an assertion. | |
91 | //! | |
92 | //! @note | |
93 | //! This macro may only be used at function scope. | |
94 | # define BOOST_HANA_ASSERT(condition) unspecified | |
95 | ||
96 | //! @ingroup group-assertions | |
97 | //! Equivalent to `BOOST_HANA_ASSERT`, but allows providing a custom | |
98 | //! failure message. | |
99 | //! | |
100 | //! @warning | |
101 | //! Conditions that contain multiple comma-separated elements should be | |
102 | //! parenthesized. | |
103 | # define BOOST_HANA_ASSERT_MSG(condition, message) unspecified | |
104 | ||
105 | //! @ingroup group-assertions | |
106 | //! Expands to a static assertion or a runtime assertion, depending on | |
107 | //! whether `constexpr` lambdas are supported. | |
108 | //! | |
109 | //! This macro is used to assert on a condition that would be a constant | |
110 | //! expression if constexpr lambdas were supported. Right now, constexpr | |
111 | //! lambdas are not supported, and this is always a runtime assertion. | |
112 | //! Specifically, this is equivalent to `BOOST_HANA_RUNTIME_ASSERT`. | |
113 | # define BOOST_HANA_CONSTEXPR_ASSERT(condition) unspecified | |
114 | ||
115 | //! @ingroup group-assertions | |
116 | //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but allows providing a | |
117 | //! custom failure message. | |
118 | # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) unspecified | |
119 | ||
120 | #elif defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS) | |
121 | ||
122 | # define BOOST_HANA_CONSTANT_ASSERT(...) /* nothing */ | |
123 | # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) /* nothing */ | |
124 | ||
125 | # define BOOST_HANA_RUNTIME_ASSERT(...) /* nothing */ | |
126 | # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) /* nothing */ | |
127 | ||
128 | # define BOOST_HANA_ASSERT(...) /* nothing */ | |
129 | # define BOOST_HANA_ASSERT_MSG(condition, message) /* nothing */ | |
130 | ||
131 | # define BOOST_HANA_CONSTEXPR_ASSERT(...) /* nothing */ | |
132 | # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) /* nothing */ | |
133 | ||
134 | #else | |
135 | ||
136 | ////////////////////////////////////////////////////////////////////////////// | |
137 | // BOOST_HANA_RUNTIME_ASSERT and BOOST_HANA_RUNTIME_ASSERT_MSG | |
138 | ////////////////////////////////////////////////////////////////////////////// | |
139 | # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) \ | |
140 | BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \ | |
141 | /**/ | |
142 | ||
143 | # define BOOST_HANA_RUNTIME_ASSERT(...) \ | |
144 | BOOST_HANA_RUNTIME_CHECK(__VA_ARGS__) \ | |
145 | /**/ | |
146 | ||
147 | ////////////////////////////////////////////////////////////////////////////// | |
148 | // BOOST_HANA_CONSTANT_ASSERT and BOOST_HANA_CONSTANT_ASSERT_MSG | |
149 | ////////////////////////////////////////////////////////////////////////////// | |
150 | # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) \ | |
151 | BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \ | |
152 | /**/ | |
153 | ||
154 | # define BOOST_HANA_CONSTANT_ASSERT(...) \ | |
155 | BOOST_HANA_CONSTANT_CHECK(__VA_ARGS__) \ | |
156 | /**/ | |
157 | ||
158 | ////////////////////////////////////////////////////////////////////////////// | |
159 | // BOOST_HANA_ASSERT and BOOST_HANA_ASSERT_MSG | |
160 | ////////////////////////////////////////////////////////////////////////////// | |
161 | # define BOOST_HANA_ASSERT_MSG(condition, message) \ | |
162 | BOOST_HANA_CHECK_MSG(condition, message) \ | |
163 | /**/ | |
164 | ||
165 | # define BOOST_HANA_ASSERT(...) \ | |
166 | BOOST_HANA_CHECK(__VA_ARGS__) \ | |
167 | /**/ | |
168 | ||
169 | ////////////////////////////////////////////////////////////////////////////// | |
170 | // BOOST_HANA_CONSTEXPR_ASSERT and BOOST_HANA_CONSTEXPR_ASSERT_MSG | |
171 | ////////////////////////////////////////////////////////////////////////////// | |
172 | # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) \ | |
173 | BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \ | |
174 | /**/ | |
175 | ||
176 | # define BOOST_HANA_CONSTEXPR_ASSERT(...) \ | |
177 | BOOST_HANA_CONSTEXPR_CHECK(__VA_ARGS__) \ | |
178 | /**/ | |
179 | ||
180 | #endif | |
181 | ||
182 | ////////////////////////////////////////////////////////////////////////////// | |
183 | // BOOST_HANA_RUNTIME_CHECK and BOOST_HANA_RUNTIME_CHECK_MSG | |
184 | ////////////////////////////////////////////////////////////////////////////// | |
185 | ||
186 | //! @ingroup group-assertions | |
187 | //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT_MSG`, but not influenced by the | |
188 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
189 | # define BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \ | |
190 | do { \ | |
191 | auto __hana_tmp = condition; \ | |
192 | static_assert(!::boost::hana::Constant<decltype(__hana_tmp)>::value,\ | |
193 | "the expression (" # condition ") yields a Constant; " \ | |
194 | "use BOOST_HANA_CONSTANT_ASSERT instead"); \ | |
195 | \ | |
196 | if (!static_cast<bool>(__hana_tmp)) { \ | |
197 | ::std::fprintf(stderr, "Assertion failed: " \ | |
198 | "(%s), function %s, file %s, line %i.\n", \ | |
199 | message, __func__, __FILE__, __LINE__); \ | |
200 | ::std::abort(); \ | |
201 | } \ | |
202 | } while (false); \ | |
203 | static_assert(true, "force trailing semicolon") \ | |
204 | /**/ | |
205 | ||
206 | //! @ingroup group-assertions | |
207 | //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but not influenced by the | |
208 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
209 | # define BOOST_HANA_RUNTIME_CHECK(...) \ | |
210 | BOOST_HANA_RUNTIME_CHECK_MSG( \ | |
211 | (__VA_ARGS__), \ | |
212 | BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \ | |
213 | ) \ | |
214 | /**/ | |
215 | ||
216 | ////////////////////////////////////////////////////////////////////////////// | |
217 | // BOOST_HANA_CONSTANT_CHECK and BOOST_HANA_CONSTANT_CHECK_MSG | |
218 | ////////////////////////////////////////////////////////////////////////////// | |
219 | ||
220 | //! @ingroup group-assertions | |
221 | //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT_MSG`, but not influenced by the | |
222 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
223 | # define BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \ | |
224 | auto BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__) = condition; \ | |
225 | static_assert(::boost::hana::Constant< \ | |
226 | decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \ | |
227 | >::value, \ | |
228 | "the expression " # condition " does not yield a Constant; " \ | |
229 | "use BOOST_HANA_RUNTIME_ASSERT instead"); \ | |
230 | static_assert(::boost::hana::value< \ | |
231 | decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \ | |
232 | >(), message); \ | |
233 | static_assert(true, "force trailing semicolon") \ | |
234 | /**/ | |
235 | ||
236 | //! @ingroup group-assertions | |
237 | //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but not influenced by the | |
238 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
239 | # define BOOST_HANA_CONSTANT_CHECK(...) \ | |
240 | BOOST_HANA_CONSTANT_CHECK_MSG( \ | |
241 | (__VA_ARGS__), \ | |
242 | BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \ | |
243 | ) \ | |
244 | /**/ | |
245 | ||
246 | ////////////////////////////////////////////////////////////////////////////// | |
247 | // BOOST_HANA_CHECK and BOOST_HANA_CHECK_MSG | |
248 | ////////////////////////////////////////////////////////////////////////////// | |
249 | ||
250 | //! @ingroup group-assertions | |
251 | //! Equivalent to `BOOST_HANA_ASSERT_MSG`, but not influenced by the | |
252 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
253 | # define BOOST_HANA_CHECK_MSG(condition, message) \ | |
254 | do { \ | |
255 | auto __hana_tmp = condition; \ | |
256 | ::boost::hana::if_(::boost::hana::bool_c< \ | |
257 | ::boost::hana::Constant<decltype(__hana_tmp)>::value>, \ | |
258 | [](auto expr) { \ | |
259 | static_assert(::boost::hana::value<decltype(expr)>(), \ | |
260 | message); \ | |
261 | }, \ | |
262 | [](auto expr) { \ | |
263 | if (!static_cast<bool>(expr)) { \ | |
264 | ::std::fprintf(stderr, "Assertion failed: " \ | |
265 | "(%s), function %s, file %s, line %i.\n", \ | |
266 | message, __func__, __FILE__, __LINE__); \ | |
267 | ::std::abort(); \ | |
268 | } \ | |
269 | } \ | |
270 | )(__hana_tmp); \ | |
271 | } while (false); \ | |
272 | static_assert(true, "force trailing semicolon") \ | |
273 | /**/ | |
274 | ||
275 | //! @ingroup group-assertions | |
276 | //! Equivalent to `BOOST_HANA__ASSERT`, but not influenced by the | |
277 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
278 | # define BOOST_HANA_CHECK(...) \ | |
279 | BOOST_HANA_CHECK_MSG( \ | |
280 | (__VA_ARGS__), \ | |
281 | BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \ | |
282 | ) \ | |
283 | /**/ | |
284 | ||
285 | ////////////////////////////////////////////////////////////////////////////// | |
286 | // BOOST_HANA_CONSTEXPR_CHECK and BOOST_HANA_CONSTEXPR_CHECK_MSG | |
287 | ////////////////////////////////////////////////////////////////////////////// | |
288 | ||
289 | //! @ingroup group-assertions | |
290 | //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by the | |
291 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
292 | # define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \ | |
293 | BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \ | |
294 | /**/ | |
295 | ||
296 | //! @ingroup group-assertions | |
297 | //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the | |
298 | //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only. | |
299 | # define BOOST_HANA_CONSTEXPR_CHECK(...) \ | |
300 | BOOST_HANA_CONSTEXPR_CHECK_MSG( \ | |
301 | (__VA_ARGS__), \ | |
302 | BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \ | |
303 | ) \ | |
304 | /**/ | |
305 | ||
306 | #endif // !BOOST_HANA_ASSERT_HPP |