|
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 | +std::false_type is_referencable_expression(...); |
| 15 | + |
| 16 | +template <typename Concept> |
| 17 | +auto is_referencable_expression(Concept c) |
| 18 | + -> decltype(c(detail::expression_decomposer<>{}), std::true_type{}); |
| 19 | + |
| 20 | +// A macro that checks whether an expression can be decomposed by the |
| 21 | +// decomposer. An expression that fails is a bitfield for example. |
| 22 | +#define LIBASSERT_IS_DECOMPOSABLE_EXPR(expr) \ |
| 23 | + decltype(libassert::detail::is_referencable_expression( \ |
| 24 | + [](auto expr_decomposer) -> decltype(std::move(expr_decomposer) \ |
| 25 | + << expr) {}))::value |
| 26 | + |
| 27 | +// The decomposer is passed as a template parameter to not evaluate the other |
| 28 | +// path and cause a hard error |
| 29 | +#define LIBASSERT_DECOMPOSER(expr) \ |
| 30 | + [&](auto decomposer) { \ |
| 31 | + if constexpr (sizeof(decomposer) && \ |
| 32 | + LIBASSERT_IS_DECOMPOSABLE_EXPR(expr)) { \ |
| 33 | + return libassert::detail::expression_decomposer(std::move(decomposer) \ |
| 34 | + << expr); \ |
| 35 | + } else { \ |
| 36 | + return std::move(decomposer) << (expr); \ |
| 37 | + } \ |
| 38 | + }(libassert::detail::expression_decomposer{}) |
| 39 | + |
| 40 | +} // namespace detail |
| 41 | +LIBASSERT_END_NAMESPACE |
| 42 | + |
| 43 | + |
11 | 44 | #if LIBASSERT_IS_CLANG || LIBASSERT_IS_GCC || !LIBASSERT_NON_CONFORMANT_MSVC_PREPROCESSOR |
12 | 45 | // Macro mapping utility by William Swanson https://github.com/swansontec/map-macro/blob/master/map.h |
13 | 46 | #define LIBASSERT_EVAL0(...) __VA_ARGS__ |
@@ -208,9 +241,7 @@ LIBASSERT_END_NAMESPACE |
208 | 241 | if constexpr(false) { (void)(expr);} \ |
209 | 242 | LIBASSERT_WARNING_PRAGMA_PUSH \ |
210 | 243 | LIBASSERT_EXPRESSION_DECOMP_WARNING_PRAGMA \ |
211 | | - auto libassert_decomposer = libassert::detail::expression_decomposer( \ |
212 | | - libassert::detail::expression_decomposer{} << expr \ |
213 | | - ); \ |
| 244 | + auto libassert_decomposer = LIBASSERT_DECOMPOSER(expr);\ |
214 | 245 | LIBASSERT_WARNING_PRAGMA_POP \ |
215 | 246 | LIBASSERT_ASSERT_MAIN_BODY( \ |
216 | 247 | expr, \ |
|
0 commit comments