|
5 | 5 | // https://github.com/jeremy-rifkin/libassert |
6 | 6 |
|
7 | 7 | #include <libassert/platform.hpp> |
8 | | - |
| 8 | +#include <libassert/expression-decomposition.hpp> |
9 | 9 | #include <string_view> |
10 | 10 |
|
| 11 | +LIBASSERT_BEGIN_NAMESPACE |
| 12 | +namespace detail { |
| 13 | + |
| 14 | +template <typename Concept, typename = void> |
| 15 | +inline constexpr bool is_referencable_expression_impl = false; |
| 16 | + |
| 17 | +template <typename Concept> |
| 18 | +inline constexpr bool is_referencable_expression_impl< |
| 19 | + Concept, |
| 20 | + decltype(void(std::declval<Concept>()(detail::expression_decomposer{})))> = true; |
| 21 | + |
| 22 | +template <typename Concept> |
| 23 | +constexpr bool is_referencable_expression(const Concept&) { |
| 24 | + return is_referencable_expression_impl<Concept>; |
| 25 | +} |
| 26 | +// A macro that checks whether an expression can be decomposed by the |
| 27 | +// decomposer. An expression that fails is a bitfield for example. |
| 28 | +#define LIBASSERT_IS_DECOMPOSABLE_EXPR(expr) \ |
| 29 | + libassert::detail::is_referencable_expression( \ |
| 30 | + [](auto expr_decomposer) -> decltype(std::move(expr_decomposer) \ |
| 31 | + << expr) {}) |
| 32 | + |
| 33 | +// The decomposer is passed as a template parameter to not evaluate the other |
| 34 | +// path and cause a hard error |
| 35 | +#define LIBASSERT_DECOMPOSER(expr) \ |
| 36 | + [&](auto decomposer) { \ |
| 37 | + if constexpr (sizeof(decomposer) && \ |
| 38 | + LIBASSERT_IS_DECOMPOSABLE_EXPR(expr)) { \ |
| 39 | + return libassert::detail::expression_decomposer(std::move(decomposer) \ |
| 40 | + << expr); \ |
| 41 | + } else { \ |
| 42 | + return std::move(decomposer) << (expr); \ |
| 43 | + } \ |
| 44 | + }(libassert::detail::expression_decomposer{}) |
| 45 | + |
| 46 | +} // namespace detail |
| 47 | +LIBASSERT_END_NAMESPACE |
| 48 | + |
| 49 | + |
11 | 50 | #if LIBASSERT_IS_CLANG || LIBASSERT_IS_GCC || !LIBASSERT_NON_CONFORMANT_MSVC_PREPROCESSOR |
12 | 51 | // Macro mapping utility by William Swanson https://github.com/swansontec/map-macro/blob/master/map.h |
13 | 52 | #define LIBASSERT_EVAL0(...) __VA_ARGS__ |
@@ -208,9 +247,7 @@ LIBASSERT_END_NAMESPACE |
208 | 247 | if constexpr(false) { (void)(expr);} \ |
209 | 248 | LIBASSERT_WARNING_PRAGMA_PUSH \ |
210 | 249 | LIBASSERT_EXPRESSION_DECOMP_WARNING_PRAGMA \ |
211 | | - auto libassert_decomposer = libassert::detail::expression_decomposer( \ |
212 | | - libassert::detail::expression_decomposer{} << expr \ |
213 | | - ); \ |
| 250 | + auto libassert_decomposer = LIBASSERT_DECOMPOSER(expr);\ |
214 | 251 | LIBASSERT_WARNING_PRAGMA_POP \ |
215 | 252 | LIBASSERT_ASSERT_MAIN_BODY( \ |
216 | 253 | expr, \ |
|
0 commit comments