WPILibC++ 2023.4.3
drake_assert.h
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4
5/// @file
6/// Provides Drake's assertion implementation. This is intended to be used
7/// both within Drake and by other software. Drake's asserts can be armed
8/// and disarmed independently from the system-wide asserts.
9
10#ifdef DRAKE_DOXYGEN_CXX
11/// @p DRAKE_ASSERT(condition) is similar to the built-in @p assert(condition)
12/// from the C++ system header @p <cassert>. Unless Drake's assertions are
13/// disarmed by the pre-processor definitions listed below, @p DRAKE_ASSERT
14/// will evaluate @p condition and iff the value is false will trigger an
15/// assertion failure with a message showing at least the condition text,
16/// function name, file, and line.
17///
18/// By default, assertion failures will :abort() the program. However, when
19/// using the pydrake python bindings, assertion failures will instead throw a
20/// C++ exception that causes a python SystemExit exception.
21///
22/// Assertions are enabled or disabled using the following pre-processor macros:
23///
24/// - If @p DRAKE_ENABLE_ASSERTS is defined, then @p DRAKE_ASSERT is armed.
25/// - If @p DRAKE_DISABLE_ASSERTS is defined, then @p DRAKE_ASSERT is disarmed.
26/// - If both macros are defined, then it is a compile-time error.
27/// - If neither are defined, then NDEBUG governs assertions as usual.
28///
29/// This header will define exactly one of either @p DRAKE_ASSERT_IS_ARMED or
30/// @p DRAKE_ASSERT_IS_DISARMED to indicate whether @p DRAKE_ASSERT is armed.
31///
32/// This header will define both `constexpr bool drake::kDrakeAssertIsArmed`
33/// and `constexpr bool drake::kDrakeAssertIsDisarmed` globals.
34///
35/// One difference versus the standard @p assert(condition) is that the
36/// @p condition within @p DRAKE_ASSERT is always syntax-checked, even if
37/// Drake's assertions are disarmed.
38///
39/// Treat @p DRAKE_ASSERT like a statement -- it must always be used
40/// in block scope, and must always be followed by a semicolon.
41#define DRAKE_ASSERT(condition)
42/// Like @p DRAKE_ASSERT, except that the expression must be void-valued; this
43/// allows for guarding expensive assertion-checking subroutines using the same
44/// macros as stand-alone assertions.
45#define DRAKE_ASSERT_VOID(expression)
46/// Evaluates @p condition and iff the value is false will trigger an assertion
47/// failure with a message showing at least the condition text, function name,
48/// file, and line.
49#define DRAKE_DEMAND(condition)
50/// Silences a "no return value" compiler warning by calling a function that
51/// always raises an exception or aborts (i.e., a function marked noreturn).
52/// Only use this macro at a point where (1) a point in the code is truly
53/// unreachable, (2) the fact that it's unreachable is knowable from only
54/// reading the function itself (and not, e.g., some larger design invariant),
55/// and (3) there is a compiler warning if this macro were removed. The most
56/// common valid use is with a switch-case-return block where all cases are
57/// accounted for but the enclosing function is supposed to return a value. Do
58/// *not* use this macro as a "logic error" assertion; it should *only* be used
59/// to silence false positive warnings. When in doubt, throw an exception
60/// manually instead of using this macro.
61#define DRAKE_UNREACHABLE()
62#else // DRAKE_DOXYGEN_CXX
63
64// Users should NOT set these; only this header should set them.
65#ifdef DRAKE_ASSERT_IS_ARMED
66# error Unexpected DRAKE_ASSERT_IS_ARMED defined.
67#endif
68#ifdef DRAKE_ASSERT_IS_DISARMED
69# error Unexpected DRAKE_ASSERT_IS_DISARMED defined.
70#endif
71
72// Decide whether Drake assertions are enabled.
73#if defined(DRAKE_ENABLE_ASSERTS) && defined(DRAKE_DISABLE_ASSERTS)
74# error Conflicting assertion toggles.
75#elif defined(DRAKE_ENABLE_ASSERTS)
76# define DRAKE_ASSERT_IS_ARMED
77#elif defined(DRAKE_DISABLE_ASSERTS) || defined(NDEBUG)
78# define DRAKE_ASSERT_IS_DISARMED
79#else
80# define DRAKE_ASSERT_IS_ARMED
81#endif
82
83namespace drake {
84namespace internal {
85// Abort the program with an error message.
86[[noreturn]] void Abort(const char* condition, const char* func,
87 const char* file, int line);
88// Report an assertion failure; will either Abort(...) or throw.
89[[noreturn]] void AssertionFailed(const char* condition, const char* func,
90 const char* file, int line);
91} // namespace internal
92namespace assert {
93// Allows for specialization of how to bool-convert Conditions used in
94// assertions, in case they are not intrinsically convertible. See
95// common/symbolic/expression/formula.h for an example use. This is a public
96// interface to extend; it is intended to be specialized by unusual Scalar
97// types that require special handling.
98template <typename Condition>
100 static constexpr bool is_valid = std::is_convertible_v<Condition, bool>;
101 static bool Evaluate(const Condition& value) {
102 return value;
103 }
104};
105} // namespace assert
106} // namespace drake
107
108#define DRAKE_UNREACHABLE() \
109 ::drake::internal::Abort( \
110 "Unreachable code was reached?!", __func__, __FILE__, __LINE__)
111
112#define DRAKE_DEMAND(condition) \
113 do { \
114 typedef ::drake::assert::ConditionTraits< \
115 typename std::remove_cv_t<decltype(condition)>> Trait; \
116 static_assert(Trait::is_valid, "Condition should be bool-convertible."); \
117 static_assert( \
118 !std::is_pointer_v<decltype(condition)>, \
119 "When using DRAKE_DEMAND on a raw pointer, always write out " \
120 "DRAKE_DEMAND(foo != nullptr), do not write DRAKE_DEMAND(foo) " \
121 "and rely on implicit pointer-to-bool conversion."); \
122 if (!Trait::Evaluate(condition)) { \
123 ::drake::internal::AssertionFailed( \
124 #condition, __func__, __FILE__, __LINE__); \
125 } \
126 } while (0)
127
128#ifdef DRAKE_ASSERT_IS_ARMED
129// Assertions are enabled.
130namespace drake {
131constexpr bool kDrakeAssertIsArmed = true;
132constexpr bool kDrakeAssertIsDisarmed = false;
133} // namespace drake
134# define DRAKE_ASSERT(condition) DRAKE_DEMAND(condition)
135# define DRAKE_ASSERT_VOID(expression) do { \
136 static_assert( \
137 std::is_convertible_v<decltype(expression), void>, \
138 "Expression should be void."); \
139 expression; \
140 } while (0)
141#else
142// Assertions are disabled, so just typecheck the expression.
143namespace drake {
144constexpr bool kDrakeAssertIsArmed = false;
145constexpr bool kDrakeAssertIsDisarmed = true;
146} // namespace drake
147# define DRAKE_ASSERT(condition) do { \
148 typedef ::drake::assert::ConditionTraits< \
149 typename std::remove_cv_t<decltype(condition)>> Trait; \
150 static_assert(Trait::is_valid, "Condition should be bool-convertible."); \
151 static_assert( \
152 !std::is_pointer_v<decltype(condition)>, \
153 "When using DRAKE_ASSERT on a raw pointer, always write out " \
154 "DRAKE_ASSERT(foo != nullptr), do not write DRAKE_ASSERT(foo) " \
155 "and rely on implicit pointer-to-bool conversion."); \
156 } while (0)
157# define DRAKE_ASSERT_VOID(expression) static_assert( \
158 std::is_convertible_v<decltype(expression), void>, \
159 "Expression should be void.")
160#endif
161
162#endif // DRAKE_DOXYGEN_CXX
then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file
Definition: ThirdPartyNotices.txt:195
Definition: core.h:1240
void Abort(const char *condition, const char *func, const char *file, int line)
void AssertionFailed(const char *condition, const char *func, const char *file, int line)
Definition: drake_assertion_error.h:6
constexpr bool kDrakeAssertIsDisarmed
Definition: drake_assert.h:132
constexpr bool kDrakeAssertIsArmed
Definition: drake_assert.h:131
Definition: Eigen_Colamd.h:50
Definition: drake_assert.h:99
static constexpr bool is_valid
Definition: drake_assert.h:100
static bool Evaluate(const Condition &value)
Definition: drake_assert.h:101