版權 © 2002, 2003 Eric Friedman, Itay Maman
版權 © 2014-2024 Antony Polukhin
依據 Boost 軟體授權條款 1.0 版發行。(請參閱隨附檔案 LICENSE_1_0.txt
或複製於 https://boost.dev.org.tw/LICENSE_1_0.txt)
目錄
variant
類別樣板是一個安全、通用、基於堆疊的可區分聯合容器,提供了一個簡單的解決方案,以統一的方式操作來自異質類型集合的物件。雖然像 std::vector
這樣的標準容器可以被認為是「多值、單一類型」,但 variant
是「多類型、單一值」。
boost::variant
的顯著特性包括:
boost::apply_visitor
進行編譯時期類型安全的值訪問。boost::get
進行執行時期檢查的顯式值檢索。boost::make_recursive_variant
和 boost::recursive_wrapper
支援遞迴變體類型。很多時候,在開發 C++ 程式時,程式設計師會發現自己需要以統一的方式操作幾種不同的類型。事實上,C++ 通過其 union
關鍵字直接提供了對這類類型的語言支援。
union { int i; double d; } u; u.d = 3.14; u.i = 3; // overwrites u.d (OK: u.d is a POD type)
然而,C++ 的 union
建構在物件導向環境中幾乎沒有用處。這個建構進入語言的主要目的是為了保持與 C 的兼容性,C 只支援 POD (Plain Old Data) 類型,因此不接受表現出非平凡建構或解構的類型。
union { int i; std::string s; // illegal: std::string is not a POD type! } u;
顯然需要另一種方法。典型的解決方案是動態分配物件,然後通過一個通用的基底類型(通常是一個虛基底類別 [Hen01] 或者,更危險的是,一個 void*
)來操作物件。然後可以通過多型向下轉型建構(例如,dynamic_cast
、boost::any_cast
等)來檢索具體類型的物件。
然而,由於以下原因,這類解決方案非常容易出錯:
此外,即使正確實作,這些解決方案由於使用了堆積、虛擬函式呼叫和多型向下轉型,往往會導致相對顯著的抽象代價。
boost::variant
類別樣板以安全、簡單且高效的方式解決了這些問題。以下範例示範了如何使用這個類別:
#include "boost/variant.hpp" #include <iostream> class my_visitor : publicboost::static_visitor
<int> { public: int operator()(int i) const { return i; } int operator()(conststd::string
& str) const { return str.length(); } }; int main() {boost::variant
< int, std::string > u("hello world"); std::cout << u; // output: hello world int result =boost::apply_visitor
( my_visitor(), u ); std::cout << result; // output: 11 (i.e., length of "hello world") }