Boost C++ 函式庫

...世界上最受推崇且設計最精良的 C++ 函式庫專案之一。 Herb SutterAndrei Alexandrescu, C++ 編碼規範

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,則無論是否定義了巨集 NDEBUGBOOST_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_MSGBOOST_ASSERT 類似,但它會額外取得一個引數,即字元常值,以提供錯誤訊息。

  • 預設情況下,BOOST_ASSERT_MSG(expr,msg) 會展開為 assert((expr)&&(msg))

  • 如果在包含 <boost/assert.hpp> 時定義了巨集 BOOST_DISABLE_ASSERTS,則無論是否定義了巨集 NDEBUGBOOST_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_MSGBOOST_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_ASSERTBOOST_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() 會傳回 filefunction_name() 會傳回 functionline() 會傳回 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

此文件

  • 版權所有 2002、2007、2014、2017、2019-2022 Peter Dimov

  • 版權所有 2011 Beman Dawes

  • 版權所有 2015 Ion Gaztañaga

  • Boost 軟體授權,版本 1.0 發佈。