Boost.Assert 函式庫提供了數個可配置的診斷巨集,其行為和用途與來自 <cassert>
的標準巨集 assert
類似。
斷言巨集,<boost/assert.hpp>
BOOST_ASSERT
標頭 <boost/assert.hpp>
定義了巨集 BOOST_ASSERT
,其與 <cassert>
中定義的標準 assert
巨集類似。此巨集旨在用於 Boost 函式庫和使用者程式碼中。
-
預設情況下,
BOOST_ASSERT(expr)
會展開為assert(expr)
。 -
如果在包含
<boost/assert.hpp>
時定義了巨集BOOST_DISABLE_ASSERTS
,則無論是否定義了巨集NDEBUG
,BOOST_ASSERT(expr)
都會展開為((void)0)
。這允許使用者有選擇性地停用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 { 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
,則無論是否定義了巨集NDEBUG
,BOOST_ASSERT_MSG(expr,msg)
都會展開為((void)0)
。 -
如果在包含
<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 { 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))
;當未定義時,會展開為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))
;當未定義時,會展開為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.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
-
依 Boost 軟體授權,版本 1.0 發佈。