Add BOOST_ASSERT_MSG. Add macros to configure output stream.

[SVN r68414]
This commit is contained in:
Beman Dawes 2011-01-24 15:37:13 +00:00
parent c58748cfd9
commit 87875cadda
3 changed files with 188 additions and 14 deletions

View File

@ -17,36 +17,89 @@
<td colspan="2" height="64">&nbsp;</td> <td colspan="2" height="64">&nbsp;</td>
</tr> </tr>
</table> </table>
<p>
<a href="#BOOST_ASSERT">BOOST_ASSERT</a><br>
<a href="#BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a><br>
<a href="#BOOST_VERIFY">BOOST_VERIFY</a></p>
<h2><a name="BOOST_ASSERT">BOOST_ASSERT</a></h2>
<p> <p>
The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT</b>, The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>. which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>.
The macro is intended to be used in Boost libraries. The macro is intended to be used in both Boost libraries and user
code.
</p> </p>
<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P> <P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P>
<P>When the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG> <P>If the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This
allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without
affecting the definition of the standard <STRONG>assert</STRONG>.</P> affecting the definition of the standard <STRONG>assert</STRONG>.</P>
<P>When the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG> <P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the
result is false, evaluates the expression</P> result is false, evaluates the expression</P>
<blockquote>
<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>, <P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P> __FILE__, __LINE__)</tt></P>
</blockquote>
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG> <P><STRONG>assertion_failed</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P> as</P>
<pre> <blockquote>
namespace boost <pre>namespace boost
{ {
void assertion_failed(char const * expr, char const * function, char const * file, long line);
void assertion_failed(char const * expr, char const * function, char const * file, long line);
} }
</pre> </pre>
</blockquote>
<p>but it is never defined. The user is expected to supply an appropriate <p>but it is never defined. The user is expected to supply an appropriate
definition.</p> definition.</p>
<P>As is the case with <STRONG>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</STRONG> <P>As is the case with <STRONG>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG> can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG>
will be redefined each time as specified above.</P> will be redefined each time as specified above.</P>
<h2><a name="BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a></h2>
<p>
The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>,
but with an additional macro parameter supplying an error message. The macro is intended to be used in both Boost libraries
and user code.
</p>
<P> <tt>BOOST_ASSERT_MSG(expr, msg)</tt> is equivalent to <code>
((void)0)</code> if <b>BOOST_DISABLE_ASSERTS</b> or <b>NDEBUG</b> are
defined or <code>expr</code> evaluates to <code>true</code>. If those
macros and <STRONG>BOOST_ENABLE_ASSERT_MSG_HANDLER</STRONG> are not
defined, and <code>expr</code> evaluates to <code>false</code>, an error
message that includes <tt>#expr</tt>, <tt>msg</tt>, <tt> <a href="current_function.html">BOOST_CURRENT_FUNCTION</a></tt>, <tt>
__FILE__</tt>, and <tt>__LINE__</tt> is sent to output stream <b>
BOOST_ASSERT_MSG_OSTREAM</b>
and <code>std::abort()</code> is called.</P>
<P> <b>BOOST_ASSERT_MSG_OSTREAM</b> defines the output stream. It defaults to <code>std::cerr</code>.
Integrated development environments (IDE's) like Microsoft Visual Studio
may produce easier to understand output if messages go to a different
stream, such as <code>std::cout</code>. Users may define <b>BOOST_ASSERT_MSG_OSTREAM</b> before including <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
to specify a different output stream.&nbsp; </P>
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_MSG_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, instead of sending a error message to an output
stream, this expression is evaluated</P>
<blockquote>
<P><tt>::boost::assertion_failed_msg(#expr, msg, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P>
</blockquote>
<P><STRONG>assertion_failed_msg</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P>
<blockquote>
<pre>namespace boost
{
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line);
}
</pre>
</blockquote>
<p>but it is never defined. The user is expected to supply an appropriate
definition.</p>
<P>As is the case with <STRONG>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT_MSG</STRONG>
will be redefined each time as specified above.</P>
<h2><a name="BOOST_VERIFY">BOOST_VERIFY</a></h2>
<p><STRONG>&lt;boost/assert.hpp&gt;</STRONG> also defines the macro <STRONG>BOOST_VERIFY</STRONG>. <p><STRONG>&lt;boost/assert.hpp&gt;</STRONG> also defines the macro <STRONG>BOOST_VERIFY</STRONG>.
It has exactly the same behavior as <STRONG>BOOST_ASSERT</STRONG>, except that It has exactly the same behavior as <STRONG>BOOST_ASSERT</STRONG>, except that
the expression that is passed to <STRONG>BOOST_VERIFY</STRONG> is always the expression that is passed to <STRONG>BOOST_VERIFY</STRONG> is always
@ -54,8 +107,9 @@ void assertion_failed(char const * expr, char const * function, char const * fil
effects; it can also help suppress warnings about unused variables when the effects; it can also help suppress warnings about unused variables when the
only use of the variable is inside an assertion.</p> only use of the variable is inside an assertion.</p>
<p><br> <p><br>
<small>Copyright © 2002, 2007 by Peter Dimov. Distributed under the Boost Software <small>Copyright © 2002, 2007 by Peter Dimov.&nbsp; Copyright © 2011
by Beman Dawes. Distributed under the Boost Software
License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body> </body>
</html> </html>

View File

@ -2,6 +2,7 @@
// assert_test.cpp - a test for boost/assert.hpp // assert_test.cpp - a test for boost/assert.hpp
// //
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (2) Beman Dawes 2011
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
@ -20,6 +21,11 @@ void test_default()
BOOST_ASSERT(x); BOOST_ASSERT(x);
BOOST_ASSERT(x == 1); BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x); BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg");
BOOST_ASSERT_MSG(x, "msg");
BOOST_ASSERT_MSG(x == 1, "msg");
BOOST_ASSERT_MSG(&x, "msg");
} }
#define BOOST_DISABLE_ASSERTS #define BOOST_DISABLE_ASSERTS
@ -34,13 +40,23 @@ void test_disabled()
BOOST_ASSERT(x == 1); BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x); BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg");
BOOST_ASSERT_MSG(x, "msg");
BOOST_ASSERT_MSG(x == 1, "msg");
BOOST_ASSERT_MSG(&x, "msg");
BOOST_ASSERT(0); BOOST_ASSERT(0);
BOOST_ASSERT(!x); BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0); BOOST_ASSERT(x == 0);
BOOST_ASSERT_MSG(0, "msg");
BOOST_ASSERT_MSG(!x, "msg");
BOOST_ASSERT_MSG(x == 0, "msg");
void * p = 0; void * p = 0;
BOOST_ASSERT(p); BOOST_ASSERT(p);
BOOST_ASSERT_MSG(p, "msg");
// supress warnings // supress warnings
p = &x; p = &x;
@ -50,11 +66,13 @@ void test_disabled()
#undef BOOST_DISABLE_ASSERTS #undef BOOST_DISABLE_ASSERTS
#define BOOST_ENABLE_ASSERT_HANDLER #define BOOST_ENABLE_ASSERT_HANDLER
#define BOOST_ENABLE_ASSERT_MSG_HANDLER
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <cstdio> #include <cstdio>
int handler_invoked = 0; int handler_invoked = 0;
int msg_handler_invoked = 0;
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
{ {
@ -66,11 +84,24 @@ void boost::assertion_failed(char const * expr, char const * function, char cons
++handler_invoked; ++handler_invoked;
} }
void boost::assertion_failed_msg(char const * expr, char const * msg, char const * function,
char const * file, long line)
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::printf;
#endif
printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n",
expr, msg, function, file, line);
++msg_handler_invoked;
}
struct X struct X
{ {
static void f() static void f()
{ {
BOOST_ASSERT(0); BOOST_ASSERT(0);
BOOST_ASSERT_MSG(0, "msg f()");
} }
}; };
@ -83,21 +114,35 @@ void test_handler()
BOOST_ASSERT(x == 1); BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x); BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg2");
BOOST_ASSERT_MSG(x, "msg3");
BOOST_ASSERT_MSG(x == 1, "msg4");
BOOST_ASSERT_MSG(&x, "msg5");
BOOST_ASSERT(0); BOOST_ASSERT(0);
BOOST_ASSERT(!x); BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0); BOOST_ASSERT(x == 0);
BOOST_ASSERT_MSG(0,"msg 0");
BOOST_ASSERT_MSG(!x, "msg !x");
BOOST_ASSERT_MSG(x == 0, "msg x == 0");
void * p = 0; void * p = 0;
BOOST_ASSERT(p); BOOST_ASSERT(p);
BOOST_ASSERT_MSG(p, "msg p");
X::f(); X::f();
BOOST_ASSERT(handler_invoked == 5); BOOST_ASSERT(handler_invoked == 5);
BOOST_TEST(handler_invoked == 5); BOOST_TEST(handler_invoked == 5);
BOOST_ASSERT_MSG(msg_handler_invoked == 5, "msg_handler_invoked count is wrong");
BOOST_TEST(msg_handler_invoked == 5);
} }
#undef BOOST_ENABLE_ASSERT_HANDLER #undef BOOST_ENABLE_ASSERT_HANDLER
#undef BOOST_ENABLE_ASSERT_MSG_HANDLER
int main() int main()
{ {

View File

@ -1,8 +1,11 @@
// //
// boost/assert.hpp - BOOST_ASSERT(expr) // boost/assert.hpp - BOOST_ASSERT(expr)
// BOOST_ASSERT_MSG(expr, msg)
// BOOST_VERIFY(expr)
// //
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2007 Peter Dimov // Copyright (c) 2007 Peter Dimov
// Copyright (c) Beman Dawes 2011
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
@ -19,6 +22,10 @@
// boostinspect:naassert_macro // boostinspect:naassert_macro
// //
//--------------------------------------------------------------------------------------//
// BOOST_ASSERT //
//--------------------------------------------------------------------------------------//
#undef BOOST_ASSERT #undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS) #if defined(BOOST_DISABLE_ASSERTS)
@ -31,18 +38,86 @@
namespace boost namespace boost
{ {
void assertion_failed(char const * expr,
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined char const * function, char const * file, long line); // user defined
} // namespace boost } // namespace boost
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) #define BOOST_ASSERT(expr) ((expr) \
? ((void)0) \
: ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else #else
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same # include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr) # define BOOST_ASSERT(expr) assert(expr)
#endif #endif
//--------------------------------------------------------------------------------------//
// BOOST_ASSERT_MSG //
//--------------------------------------------------------------------------------------//
# undef BOOST_ASSERT_MSG
#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
#define BOOST_ASSERT_MSG(expr, msg) ((void)0)
#elif defined(BOOST_ENABLE_ASSERT_MSG_HANDLER)
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed_msg(char const * expr, char const * msg,
char const * function, char const * file, long line); // user defined
} // namespace boost
#define BOOST_ASSERT_MSG(expr, msg) ((expr) \
? ((void)0) \
: ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
#ifndef BOOST_ASSERT_HPP
#define BOOST_ASSERT_HPP
#include <cstdlib>
#include <iostream>
#include <boost/current_function.hpp>
// IDE's like Visual Studio perform better if output goes to std::cout or
// some other stream, so allow user to configure output stream:
#ifndef BOOST_ASSERT_MSG_OSTREAM
# define BOOST_ASSERT_MSG_OSTREAM std::cerr
#endif
namespace boost
{
namespace assertion
{
namespace detail
{
inline void assertion_failed_msg(char const * expr, char const * msg, char const * function,
char const * file, long line)
{
BOOST_ASSERT_MSG_OSTREAM
<< "***** Internal Program Error - assertion (" << expr << ") failed in "
<< function << ":\n"
<< file << '(' << line << "): " << msg << std::endl;
std::abort();
}
} // detail
} // assertion
} // detail
#endif
#define BOOST_ASSERT_MSG(expr, msg) ((expr) \
? ((void)0) \
: ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \
BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#endif
//--------------------------------------------------------------------------------------//
// BOOST_VERIFY //
//--------------------------------------------------------------------------------------//
#undef BOOST_VERIFY #undef BOOST_VERIFY
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) ) #if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )