![]() |
Home | Libraries | People | FAQ | More |
Copyright c 2002, 2003 Eric Friedman, Itay Maman
Permission to copy, use, sell and distribute this software is granted provided this copyright notice appears in all copies. Permission to modify the code and to distribute modified code is granted provided this copyright notice appears in all copies, and a notice that the code was modified is included with the copyright notice.
This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
目錄
variant 類模板是一個安全的、泛型的、基於棧的、可識別的聯合容器,為以統一風格操作異類類型集合的對象提供了一個簡單的方法。像 std::vector 這樣的標準容器可以被視為
"多值,單一類型",而 variant 則是 "多類型,單值"。
boost::variant
的主要特性包括:
boost::apply_visitor 的編譯期類型安全的值訪問。boost::get 的運行期帶檢查的顯式的值取出。boost::make_recursive_variant 和
boost::recursive_wrapper 支持遞歸的 variant 類型。很多時候,在開發一個C++程序時,程序員會發現需要以統一的風格來操作多個不同的類型。確實,C++以 union
關鍵字直接提供了這種支持:
union { int i; double d; } u;
u.d = 3.14;
u.i = 3; // 覆寫 u.d (OK: u.d 是一個 POD 類型)
但是,C++的 union 結構在面向對象的環境下幾乎是不可用的。該結構得以保存下來,主要是為了與C兼容,它只能支持 POD (Plain Old Data) 類型,不可以使用帶有非平凡構造或析構的類型:
union {
int i;
std::string s; // 非法: std::string 不是一個 POD 類型!
} 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")
}