4545
4646#ifndef DEBUG_ASSERT_ASSUME
4747#ifdef __GNUC__
48- #define DEBUG_ASSERT_ASSUME (Expr ) \
49- do { \
50- if (!(Expr)) \
51- __builtin_unreachable (); \
52- } while (0 )
48+ #define DEBUG_ASSERT_ASSUME (Expr ) \
49+ do \
50+ { \
51+ if (!(Expr)) \
52+ __builtin_unreachable (); \
53+ } while (0 )
5354#elif defined(_MSC_VER)
5455#define DEBUG_ASSERT_ASSUME (Expr ) __assume(Expr)
5556#else
7172#endif
7273#endif
7374
74- namespace debug_assert {
75- // === source location ===//
76- // / Defines a location in the source code.
77- struct source_location {
78- const char *file_name; // /< The file name.
79- unsigned line_number; // /< The line number.
80- };
75+ namespace debug_assert
76+ {
77+ // === source location ===//
78+ // / Defines a location in the source code.
79+ struct source_location
80+ {
81+ const char * file_name; // /< The file name.
82+ unsigned line_number; // /< The line number.
83+ };
8184
8285// / Expands to the current [debug_assert::source_location]().
83- #define DEBUG_ASSERT_CUR_SOURCE_LOCATION \
84- debug_assert::source_location { __FILE__, __LINE__ }
86+ #define DEBUG_ASSERT_CUR_SOURCE_LOCATION \
87+ debug_assert::source_location \
88+ { \
89+ __FILE__, __LINE__ \
90+ }
8591
86- // === level ===//
87- // / Tag type to indicate the level of an assertion.
88- template <unsigned Level> struct level {};
92+ // === level ===//
93+ // / Tag type to indicate the level of an assertion.
94+ template <unsigned Level>
95+ struct level
96+ {
97+ };
8998
90- // / Helper class that sets a certain level.
91- // / Inherit from it in your module handler.
92- template <unsigned Level> struct set_level {
93- static const unsigned level = Level;
94- };
99+ // / Helper class that sets a certain level.
100+ // / Inherit from it in your module handler.
101+ template <unsigned Level>
102+ struct set_level
103+ {
104+ static const unsigned level = Level;
105+ };
95106
96- template <unsigned Level> const unsigned set_level<Level>::level;
107+ template <unsigned Level>
108+ const unsigned set_level<Level>::level;
97109
98- // === handler ===//
99- // / Does not do anything to handle a failed assertion (except calling
100- // / [std::abort()]()).
101- // / Inherit from it in your module handler.
102- struct no_handler {
103- // / \effects Does nothing.
104- // / \notes Can take any additional arguments.
105- template <typename ... Args>
106- static void handle (const source_location &, const char *,
107- Args &&...) noexcept {}
108- };
110+ // === handler ===//
111+ // / Does not do anything to handle a failed assertion (except calling
112+ // / [std::abort()]()).
113+ // / Inherit from it in your module handler.
114+ struct no_handler
115+ {
116+ // / \effects Does nothing.
117+ // / \notes Can take any additional arguments.
118+ template <typename ... Args>
119+ static void handle (const source_location&, const char *, Args&&...) noexcept
120+ {
121+ }
122+ };
109123
110- // / The default handler that writes a message to `stderr`.
111- // / Inherit from it in your module handler.
112- struct default_handler {
113- // / \effects Prints a message to `stderr`.
114- // / \notes It can optionally accept an additional message string.
115- // / \notes If `DEBUG_ASSERT_NO_STDIO` is defined, it will do nothing.
116- static void handle (const source_location &loc, const char *expression,
117- const char *message = nullptr ) noexcept {
124+ // / The default handler that writes a message to `stderr`.
125+ // / Inherit from it in your module handler.
126+ struct default_handler
127+ {
128+ // / \effects Prints a message to `stderr`.
129+ // / \notes It can optionally accept an additional message string.
130+ // / \notes If `DEBUG_ASSERT_NO_STDIO` is defined, it will do nothing.
131+ static void handle (const source_location& loc, const char * expression,
132+ const char * message = nullptr ) noexcept
133+ {
118134#ifndef DEBUG_ASSERT_NO_STDIO
119- if (*expression == ' \0 ' ) {
120- if (message)
121- std::fprintf (stderr,
122- " [debug assert] %s:%u: Unreachable code reached - %s.\n " ,
123- loc.file_name , loc.line_number , message);
124- else
125- std::fprintf (stderr,
126- " [debug assert] %s:%u: Unreachable code reached.\n " ,
127- loc.file_name , loc.line_number );
128- } else if (message)
129- std::fprintf (stderr,
130- " [debug assert] %s:%u: Assertion '%s' failed - %s.\n " ,
131- loc.file_name , loc.line_number , expression, message);
132- else
133- std::fprintf (stderr, " [debug assert] %s:%u: Assertion '%s' failed.\n " ,
134- loc.file_name , loc.line_number , expression);
135+ if (*expression == ' \0 ' )
136+ {
137+ if (message)
138+ std::fprintf (stderr, " [debug assert] %s:%u: Unreachable code reached - %s.\n " ,
139+ loc.file_name , loc.line_number , message);
140+ else
141+ std::fprintf (stderr, " [debug assert] %s:%u: Unreachable code reached.\n " ,
142+ loc.file_name , loc.line_number );
143+ }
144+ else if (message)
145+ std::fprintf (stderr, " [debug assert] %s:%u: Assertion '%s' failed - %s.\n " ,
146+ loc.file_name , loc.line_number , expression, message);
147+ else
148+ std::fprintf (stderr, " [debug assert] %s:%u: Assertion '%s' failed.\n " ,
149+ loc.file_name , loc.line_number , expression);
135150#else
136- (void )loc;
137- (void )expression;
138- (void )message;
151+ (void )loc;
152+ (void )expression;
153+ (void )message;
139154#endif
140- }
141- };
155+ }
156+ };
142157
143- // / \exclude
144- namespace detail {
145- // === boilerplate ===//
146- // from http://en.cppreference.com/w/cpp/types/remove_reference
147- template <typename T> struct remove_reference { using type = T; };
158+ // / \exclude
159+ namespace detail
160+ {
161+ // === boilerplate ===//
162+ // from http://en.cppreference.com/w/cpp/types/remove_reference
163+ template <typename T>
164+ struct remove_reference
165+ {
166+ using type = T;
167+ };
148168
149- template <typename T> struct remove_reference <T &> { using type = T; };
169+ template <typename T>
170+ struct remove_reference <T&>
171+ {
172+ using type = T;
173+ };
150174
151- template <typename T> struct remove_reference <T &&> { using type = T; };
175+ template <typename T>
176+ struct remove_reference <T&&>
177+ {
178+ using type = T;
179+ };
152180
153- // from http://stackoverflow.com/a/27501759
154- template <class T > T &&forward(typename remove_reference<T>::type &t) {
155- return static_cast <T &&>(t);
156- }
181+ // from http://stackoverflow.com/a/27501759
182+ template <class T >
183+ T&& forward(typename remove_reference<T>::type& t)
184+ {
185+ return static_cast <T&&>(t);
186+ }
157187
158- template <class T > T &&forward(typename remove_reference<T>::type &&t) {
159- return static_cast <T &&>(t);
160- }
188+ template <class T >
189+ T&& forward(typename remove_reference<T>::type&& t)
190+ {
191+ return static_cast <T&&>(t);
192+ }
161193
162- template <bool Value> struct enable_if ;
194+ template <bool Value>
195+ struct enable_if ;
163196
164- template <> struct enable_if <true > { using type = void ; };
197+ template <>
198+ struct enable_if <true >
199+ {
200+ using type = void ;
201+ };
165202
166- template <> struct enable_if <false > {};
203+ template <>
204+ struct enable_if <false >
205+ {
206+ };
167207
168- // === assert implementation ===//
169- // use enable if instead of tag dispatching
170- // this removes on additional function and encourage optimization
171- template <class Expr , class Handler , unsigned Level, typename ... Args>
172- auto do_assert (const Expr &expr, const source_location &loc,
173- const char *expression, Handler, level<Level>,
174- Args &&... args) noexcept ->
175- typename enable_if<Level <= Handler::level>::type {
176- static_assert (Level > 0 , " level of an assertion must not be 0" );
177- if (!expr ()) {
178- Handler::handle (loc, expression, forward<Args>(args)...);
179- std::abort ();
180- }
181- }
208+ // === assert implementation ===//
209+ // use enable if instead of tag dispatching
210+ // this removes on additional function and encourage optimization
211+ template <class Expr , class Handler , unsigned Level, typename ... Args>
212+ auto do_assert (const Expr& expr, const source_location& loc, const char * expression,
213+ Handler, level<Level>, Args&&... args) noexcept ->
214+ typename enable_if<Level <= Handler::level>::type
215+ {
216+ static_assert (Level > 0 , " level of an assertion must not be 0" );
217+ if (!expr ())
218+ {
219+ Handler::handle (loc, expression, forward<Args>(args)...);
220+ std::abort ();
221+ }
222+ }
182223
183- template <class Expr , class Handler , unsigned Level, typename ... Args>
184- DEBUG_ASSERT_FORCE_INLINE auto
185- do_assert (const Expr &expr, const source_location &, const char *, Handler,
186- level<Level>, Args &&...) noexcept ->
187- typename enable_if<(Level > Handler::level)>::type {
188- DEBUG_ASSERT_ASSUME (expr ());
189- }
224+ template <class Expr , class Handler , unsigned Level, typename ... Args>
225+ DEBUG_ASSERT_FORCE_INLINE auto do_assert (const Expr& expr, const source_location&,
226+ const char *, Handler, level<Level>,
227+ Args&&...) noexcept ->
228+ typename enable_if<(Level > Handler::level)>::type
229+ {
230+ DEBUG_ASSERT_ASSUME (expr ());
231+ }
190232
191- template <class Expr , class Handler , typename ... Args>
192- auto do_assert (const Expr &expr, const source_location &loc,
193- const char *expression, Handler, Args &&... args) noexcept ->
194- typename enable_if<Handler::level != 0>::type {
195- if (!expr ()) {
196- Handler::handle (loc, expression, forward<Args>(args)...);
197- std::abort ();
198- }
199- }
233+ template <class Expr , class Handler , typename ... Args>
234+ auto do_assert (const Expr& expr, const source_location& loc, const char * expression,
235+ Handler, Args&&... args) noexcept ->
236+ typename enable_if<Handler::level != 0>::type
237+ {
238+ if (!expr ())
239+ {
240+ Handler::handle (loc, expression, forward<Args>(args)...);
241+ std::abort ();
242+ }
243+ }
200244
201- template <class Expr , class Handler , typename ... Args>
202- DEBUG_ASSERT_FORCE_INLINE auto do_assert (const Expr & expr,
203- const source_location &, const char *,
204- Handler, Args &&...) noexcept ->
205- typename enable_if<Handler::level == 0>::type {
206- DEBUG_ASSERT_ASSUME (expr ());
207- }
208- } // namespace detail
245+ template <class Expr , class Handler , typename ... Args>
246+ DEBUG_ASSERT_FORCE_INLINE auto do_assert (const Expr& expr, const source_location& ,
247+ const char *, Handler, Args&&...) noexcept ->
248+ typename enable_if< Handler::level == 0>::type
249+ {
250+ DEBUG_ASSERT_ASSUME (expr ());
251+ }
252+ } // namespace detail
209253} // namespace debug_assert
210254
211255// === assertion macros ===//
@@ -235,10 +279,9 @@ DEBUG_ASSERT_FORCE_INLINE auto do_assert(const Expr &expr,
235279// / will expand to nothing.
236280// / This should not be necessary, the regular version is optimized away
237281// / completely.
238- #define DEBUG_ASSERT (Expr, ...) \
239- debug_assert::detail::do_assert ([&] { return Expr; }, \
240- DEBUG_ASSERT_CUR_SOURCE_LOCATION, #Expr, \
241- __VA_ARGS__)
282+ #define DEBUG_ASSERT (Expr, ...) \
283+ debug_assert::detail::do_assert ([&] { return Expr; }, DEBUG_ASSERT_CUR_SOURCE_LOCATION, #Expr, \
284+ __VA_ARGS__)
242285
243286// / Marks a branch as unreachable.
244287// /
@@ -260,10 +303,9 @@ DEBUG_ASSERT_FORCE_INLINE auto do_assert(const Expr &expr,
260303// / will expand to `DEBUG_ASSERT_MARK_UNREACHABLE`.
261304// / This should not be necessary, the regular version is optimized away
262305// / completely.
263- #define DEBUG_UNREACHABLE (...) \
264- debug_assert::detail::do_assert ([&] { return false ; }, \
265- DEBUG_ASSERT_CUR_SOURCE_LOCATION, " " , \
266- __VA_ARGS__)
306+ #define DEBUG_UNREACHABLE (...) \
307+ debug_assert::detail::do_assert ([&] { return false ; }, DEBUG_ASSERT_CUR_SOURCE_LOCATION, " " , \
308+ __VA_ARGS__)
267309#else
268310#define DEBUG_ASSERT (Expr, ...) DEBUG_ASSERT_ASSUME(Expr)
269311
0 commit comments