boost的variant庫類似於聯合體,但是聯合體中只能接受POD類型,但variant中並無此限制,它可以接受任意的類型.
boost::variant <int, std::string , double> u;
u
= 4;
int i = boost:: get<int >(u);
std::cout << "int : " << i << std ::endl;
u = "hello world!" ;
std::string s = boost::get <std:: string>(u );
std::cout << "string : " << s << std ::endl;
u
= 1.2;
double d = boost:: get<double >(u);
std::cout << "double : " << d << std ::endl;
輸出:
int : 4
string : hello world!
double : 1.2
string : hello world!
double : 1.2
要獲取variant中的值時,一定要知道當前類型,並由get操作進行獲取相應的值,如果轉型失敗,會拋出bad_get異常,get操作時運行時檢測,我們可以通過檢測get返回值來進行判斷轉型是否成功如下:
void
printer
(
boost
::
variant
<
int
,
std
::
string
,
double
>&
u
)
{
if
(
int
*
pi
=
boost
::
get
<
int
>(&
u
))
{
std
::
cout
<<
"int : "
<< *
pi
<<
std
::
endl
;
}
else
if
(
std
::
string
*
ps
=
boost
::
get
<
std
::
string
>(&
u
))
{
std
::
cout
<<
"string : "
<< *
ps
<<
std
::
endl
;
}
else
if
(
double
*
pd
=
boost
::
get
<
double
>(&
u
))
{
std
::
cout
<<
"double : "
<< *
pd
<<
std
::
endl
;
}
}
通過printer函數中我們為get傳進去的是variant的地址,返回如果是NULL的話則轉型失敗,進行下一個轉型操作,依次來判斷數據類型.可以看到通過get操作不僅需要知道需要轉型的類型,而且還要在運行時判斷轉型是否成功,boost提供了編譯時類型檢測的安全訪問方式,通過apply_visitor進行訪問.
class
printer_visitor
:
public
boost
::
static_visitor
<
void
>
{
public
:
void
operator
()(
int
i
)
const
{
std
::
cout
<<
"int : "
<<
i
<<
std
::
endl
;
}
void
operator
()(
std
::
string
&
s
)
const
{
std
::
cout
<<
"string : "
<<
s
<<
std
::
endl
;
}
void
operator
()(
double
d
)
const
{
std
::
cout
<<
"double : "
<<
d
<<
std
::
endl
;
}
};
int
main
()
{
boost
::
variant
<
int
,
std
::
string
,
double
>
u
;
printer_visitor
visitor
;
u
= 4;
boost
::
apply_visitor
(
visitor
,
u
);
u
=
"hello world!"
;
boost
::
apply_visitor
(
visitor
,
u
);
u
= 1.2;
boost
::
apply_visitor
(
visitor
,
u
);
}
我們定義一個variant時,如果我們沒有給它賦任何值時,是不是他就是空呢?boost文檔中
"Never-Empty" Guarantee.也就是即使我們沒有初始化,他也不會是空,默認的類型是我們模板參數的第一個,上例中默認的類型也就是int,值是0.
我們還可以將variant作為容器的元素例如:
std
::
vector
<
boost
::
variant
<
int
,
std
::
string
,
double
> >
v
;
v
.
push_back
(4);
v
.
push_back
(
"hello world!"
);
v
.
push_back
(1.2);
std
::
for_each
(
v
.
begin
(),
v
.
end
(),
boost
::
apply_visitor
(
printer_visitor
()));