KASSERT  0.0.1
Karlsruhe Assertion Library
expression_decomposition.hpp File Reference

Expression decomposition. More...

#include <type_traits>
#include "kassert/internal/logger.hpp"

Go to the source code of this file.

Classes

struct  kassert::internal::AlwaysFalse< T >
 Type trait that is always false, to implement static_asserts that always fail, thus preventing a template function from being instanciated. Used to forbid calling the overloads of && and ||. More...
 
class  kassert::internal::Expression
 Interface for decomposed unary and binary expressions. More...
 
class  kassert::internal::BinaryExpression< LhsT, RhsT >
 A decomposed binary expression. More...
 
class  kassert::internal::UnaryExpression< LhsT >
 Decomposed unary expression. More...
 
class  kassert::internal::LhsExpression< LhsT >
 The left hand size of a decomposed expression. This can either be turned into a BinaryExpr if an operand or relation follows, or into a UnaryExpr otherwise. More...
 
struct  kassert::internal::Decomposer
 Decomposes an expression (see group description). More...
 

Functions

bool kassert::internal::finalize_expr (bool const result)
 If an expression cannot be decomposed (due to && or ||, to preserve short-circuit evaluation), simply return the result of the assertion. More...
 
template<typename ExprT >
decltype(auto) kassert::internal::finalize_expr (ExprT &&expr)
 Transforms LhsExpression into UnaryExpression, does nothing to a Expression (see group description). More...
 

Detailed Description

Expression decomposition.

Failed assertions try to expand the expression similar to what Catch2 does. This is achieved by the following process:

In a call

KASSERT(rhs == lhs)
#define KASSERT(...)
Assertion macro. Accepts between one and three parameters.
Definition: kassert.hpp:60

KASSERT() also prints the values of rhs and lhs. However, this expression expansion is limited and only works for expressions that do not contain parentheses, but are implicitly left-associative. This is due to its implementation:

KASSERT(rhs == lhs)

is replaced by

Decomposer{} <= rhs == lhs

which is interpreted by the compiler as

((Decomposer{} <= rhs) == lhs)

where the first <= relation is overloaded to return a proxy object which in turn overloads other operators. If the expression is not implicitly left-associative or contains parentheses, this does not work:

KASSERT(rhs1 == lhs1 && rhs2 == lhs2)

is replaced by (with implicit parentheses)

((Decomposer{} <= rhs1) == lhs1) && (rhs2 == lhs2))

Thus, the left hand side of && can only be expanded to the result of rhs2 == lhs2. This limitation only affects the error message, not the interpretation of the expression itself.

Function Documentation

◆ finalize_expr() [1/2]

bool kassert::internal::finalize_expr ( bool const  result)
inline

If an expression cannot be decomposed (due to && or ||, to preserve short-circuit evaluation), simply return the result of the assertion.

Parameters
resultResult of the assertion.
Returns
Result of the assertion.

◆ finalize_expr() [2/2]

template<typename ExprT >
decltype(auto) kassert::internal::finalize_expr ( ExprT &&  expr)

Transforms LhsExpression into UnaryExpression, does nothing to a Expression (see group description).

Template Parameters
ExprTType of the expression, either LhsExpression or a BinaryExpression.
Parameters
exprThe expression.
Returns
The expression as some subclass of Expression.