Boost.Assert 库提供了一些可配置的诊断宏,其行为和目的类似于标准库中的 assert
宏(来自 <cassert>
)。
断言宏,<boost/assert.hpp>
BOOST_ASSERT
头文件 <boost/assert.hpp>
定义了宏 BOOST_ ASSERT
,它类似于 <cassert>
中定义的标准 assert
宏。该宏旨在用于 Boost 库和用户代码中。
-
默认情况下,
BOOST_ ASSERT(expr)
展开为assert(expr)
。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_DISABLE_ASSERTS
,则BOOST_ ASSERT(expr)
将展开为((void)0)
,无论是否定义了宏NDEBUG
。这允许用户选择性地禁用BOOST_ ASSERT
,而不会影响标准assert
的定义。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_HANDLER
,则BOOST_ ASSERT(expr)
展开为(BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
也就是说,它会计算
expr
,如果表达式为 false,则调用::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)
。无论是否定义了NDEBUG
,这种情况都成立。boost::assertion_failed
在<boost/assert.hpp>
中声明为namespace boost { #if defined(BOOST_ASSERT_HANDLER_IS_NORETURN) BOOST_NORETURN #endif void assertion_failed(char const * expr, char const * function, char const * file, long line); }
但它从不被定义。用户需要提供适当的定义。
-
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_DEBUG_HANDLER
,则当定义了NDEBUG
时,BOOST_ ASSERT(expr)
展开为((void)0)
。否则,其行为与定义了BOOST_ENABLE_ASSERT_HANDLER
时相同。
与 <cassert>
的情况一样,<boost/assert.hpp>
可以在单个翻译单元中包含多次。BOOST_ ASSERT
会根据上述说明每次重新定义。
BOOST_ASSERT_MSG
宏 BOOST_ASSERT_MSG
与 BOOST_ASSERT
类似,但它接受一个额外的参数,即一个字符字面量,用于提供错误消息。
-
默认情况下,
BOOST_ASSERT_MSG(expr,msg)
展开为assert((expr)&&(msg))
。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_DISABLE_ASSERTS
,则BOOST_ASSERT_MSG(expr,msg)
将展开为((void)0)
,无论是否定义了宏NDEBUG
。这允许用户选择性地禁用BOOST_ASSERT_MSG
,而不会影响标准assert
的定义。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_HANDLER
,则BOOST_ASSERT_MSG(expr,msg)
展开为(BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
无论是否定义了
NDEBUG
,这种情况都成立。boost::assertion_failed_msg
在<boost/assert.hpp>
中声明为namespace boost { #if defined(BOOST_ASSERT_HANDLER_IS_NORETURN) BOOST_NORETURN #endif void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line); }
但它从不被定义。用户需要提供适当的定义。
-
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_DEBUG_HANDLER
,则当定义了NDEBUG
时,BOOST_ASSERT_MSG(expr)
展开为((void)0)
。否则,其行为与定义了BOOST_ENABLE_ASSERT_HANDLER
时相同。
与 <cassert>
的情况一样,<boost/assert.hpp>
可以在单个翻译单元中包含多次。BOOST_ASSERT_MSG
会根据上述说明每次重新定义。
BOOST_VERIFY
宏 BOOST_VERIFY
的行为与 BOOST_ASSERT
相同,只是传递给 BOOST_VERIFY
的表达式始终会被计算。这在断言表达式具有期望的副作用时很有用;它还可以帮助抑制关于未使用变量的警告,当变量的唯一用途是在断言中时。
-
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_DISABLE_ASSERTS
,则BOOST_VERIFY(expr)
展开为((void)(expr))
。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_HANDLER
,则BOOST_VERIFY(expr)
展开为BOOST_ASSERT(expr)
。 -
否则,当定义了
NDEBUG
时,BOOST_VERIFY(expr)
展开为((void)(expr))
;当未定义NDEBUG
时,则展开为BOOST_ASSERT(expr)
。
BOOST_VERIFY_MSG
宏 BOOST_VERIFY_MSG
与 BOOST_VERIFY
类似,但增加了一个额外的参数,即一个错误消息。
-
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_DISABLE_ASSERTS
,则BOOST_VERIFY_MSG(expr,msg)
展开为((void)(expr))
。 -
如果在包含
<boost/assert.hpp>
时定义了宏BOOST_ENABLE_ASSERT_HANDLER
,则BOOST_VERIFY_MSG(expr,msg)
展开为BOOST_ASSERT_MSG(expr,msg)
。 -
否则,当定义了
NDEBUG
时,BOOST_VERIFY_MSG(expr,msg)
展开为((void)(expr))
;当未定义NDEBUG
时,则展开为BOOST_ASSERT_MSG(expr,msg)
。
BOOST_ASSERT_IS_VOID
当 BOOST_ASSERT
和 BOOST_ASSERT_MSG
展开为 ((void)0)
时,定义宏 BOOST_ASSERT_IS_VOID
。它的目的是避免编译和可能运行仅用于准备断言数据的代码。
void MyContainer::erase(iterator i)
{
// Some sanity checks, data must be ordered
#ifndef BOOST_ASSERT_IS_VOID
if(i != c.begin()) {
iterator prev = i;
--prev;
BOOST_ASSERT(*prev < *i);
}
else if(i != c.end()) {
iterator next = i;
++next;
BOOST_ASSERT(*i < *next);
}
#endif
this->erase_impl(i);
}
-
默认情况下,如果定义了
NDEBUG
,则定义BOOST_ASSERT_IS_VOID
。 -
如果定义了宏
BOOST_DISABLE_ASSERTS
,则始终定义BOOST_ASSERT_IS_VOID
。 -
如果定义了宏
BOOST_ENABLE_ASSERT_HANDLER
,则永不定义BOOST_ASSERT_IS_VOID
。 -
如果定义了宏
BOOST_ENABLE_ASSERT_DEBUG_HANDLER
,则当定义了NDEBUG
时,定义BOOST_ASSERT_IS_VOID
。
当前函数宏,<boost/current_function.hpp>
BOOST_CURRENT_FUNCTION
头文件 <boost/current_function.hpp>
定义了一个宏 BOOST_CURRENT_FUNCTION
,它类似于 C99 的预定义标识符 __func__
。
BOOST_CURRENT_FUNCTION
展开为字符串字面量,或者展开为当前函数局部的一个字符数组名,其中包含(如果可能)当前嵌套函数的(完全限定)名称。如果没有嵌套函数,则行为因编译器而异,但通常会导致编译错误。
某些编译器不提供获取当前嵌套函数名称的方法。在这些编译器上,或者当定义了宏 BOOST_DISABLE_CURRENT_FUNCTION
时,BOOST_CURRENT_FUNCTION
将展开为 "(unknown)"
。
BOOST_DISABLE_CURRENT_FUNCTION
解决了程序员出于安全原因希望从最终可执行文件中删除 BOOST_CURRENT_FUNCTION
生成的字符串字面量的用例。
源位置支持,<boost/assert/source_location.hpp>
描述
头文件 <boost/assert/source_location.hpp>
定义了 source_location
类,该类表示一个源位置,包含文件、行、函数和列信息。它类似于 C++20 的 std::source_location
,但只需要 C++03。
宏 BOOST_CURRENT_LOCATION
创建一个 source_location
对象,其中包含当前源位置的信息。它的用法与 std::source_location::current()
类似,例如在函数默认参数的声明中使用
#include <boost/assert/source_location.hpp>
#include <iostream>
void f( boost::source_location const& loc = BOOST_CURRENT_LOCATION )
{
std::cout << "f() called from: " << loc << std::endl;
}
int main()
{
f();
}
此示例的输出因编译器和 C++ 标准级别而异,但通常是以下之一:
f() called from: example.cpp:11:6 in function 'int main()'
f() called from: example.cpp:11:5 in function 'main'
f() called from: example.cpp:11 in function 'main'
f() called from: example.cpp:4
例如,如果您想声明一个会抛出异常的函数,以便将调用者的源位置附加到抛出的异常,这会很有用。
BOOST_NORETURN BOOST_NOINLINE void throw_invalid_argument(
char const* message,
boost::source_location const& loc = BOOST_CURRENT_LOCATION )
{
boost::throw_exception( std::invalid_argument( message ), loc );
}
现在,您可以在例如 at
函数的实现中使用这个辅助函数来指示数组索引越界。
T& my_class::at( size_t i )
{
if( i >= size() ) throw_invalid_argument( "index out of range" );
return data()[ i ];
}
这将把 at
中调用 throw_invalid_argument
的那一行代码的源位置附加到抛出的异常。
请注意,如果您在 throw_invalid_argument
中改用 BOOST_THROW_EXCEPTION
,则位置将是 throw_invalid_argument
的位置,而不是其调用者的位置。
提要
namespace boost
{
struct source_location
{
constexpr source_location() noexcept;
constexpr source_location( char const* file, uint_least32_t line,
char const* function, uint_least32_t column = 0 ) noexcept;
constexpr source_location( std::source_location const& loc ) noexcept;
constexpr char const* file_name() const noexcept;
constexpr char const* function_name() const noexcept;
constexpr uint_least32_t line() const noexcept;
constexpr uint_least32_t column() const noexcept;
std::string to_string() const;
};
template<class E, class T>
std::basic_ostream<E, T> &
operator<<( std::basic_ostream<E, T> & os, source_location const & loc );
} // namespace boost
#define BOOST_CURRENT_LOCATION /* see below */
source_location
constexpr source_location() noexcept;
- 效果
-
构造一个
source_location
对象,其中file_name()
和function_name()
返回""
,而line()
和column()
返回0
。
constexpr source_location( char const* file, uint_least32_t line,
char const* function, uint_least32_t column = 0 ) noexcept;
- 效果
-
构造一个
source_location
对象,其中file_name()
返回file
,function_name()
返回function
,line()
返回line
参数,column()
返回column
参数。
constexpr source_location( std::source_location const& loc ) noexcept;
- 效果
-
构造一个
source_location
对象,其中file_name()
返回loc.file_name()
,function_name()
返回loc.function_name()
,line()
返回loc.line()
,column()
返回loc.column()
。
to_string
std::string to_string() const;
- 返回
-
*this
的字符串表示。
operator<<
template<class E, class T>
std::basic_ostream<E, T> &
operator<<( std::basic_ostream<E, T> & os, source_location const & loc );
- 效果
-
os << loc.to_string()
. - 返回
-
os
.
BOOST_CURRENT_LOCATION
当定义了 BOOST_DISABLE_CURRENT_LOCATION
时,BOOST_CURRENT_LOCATION
的定义是
#define BOOST_CURRENT_LOCATION ::boost::source_location()
这允许生成不包含标识信息的(无标识符的)可执行文件,以提高安全性。
否则,BOOST_CURRENT_LOCATION
定义为近似等价于
#define BOOST_CURRENT_LOCATION \
::boost::source_location(::std::source_location::current())
修订历史
1.88.0 版中的更改
-
当定义了
BOOST_ASSERT_HANDLER_IS_NORETURN
时,boost::assertion_failed
和boost::assertion_failed_msg
被声明为BOOST_NORETURN
。
1.79.0 版中的更改
-
source_location().file_name()
和source_location().function_name()
现在返回""
而不是"(unknown)"
。 -
添加了从
std::source_location
构造source_location
的构造函数。 -
将
BOOST_CURRENT_LOCATION
更改为更接近std::source_location::current()
的行为,例如可以在顶层使用或作为默认函数参数。
1.78.0 版的更改
-
添加了
source_location::to_string
。
1.73.0 版的更改
-
添加了
source_location
。
附录 A:版权与许可
本文档
-
版权 2002, 2007, 2014, 2017, 2019-2022 Peter Dimov
-
版权 2011 Beman Dawes
-
版权 2015 Ion Gaztañaga