2013-07-18 58 views
6

我需要創建聯合,但聯合的兩個成員具有相同類型,因此我需要一種方法來識別它們。例如在OCaml中:多次使用相同類型在C++中標記的聯合(又名變體)

type A = 
    | B of int 
    | C of float 
    | D of float 

Boost.Variant似乎不支持這種情況,是否有支持這種情況的已知庫?

+3

爲什麼兩個相同的'type'?任何時候只能使用一個工會會員。 – hmjd

+2

我知道,但有些情況下,即使他們具有相同的基礎類型,您也想對成員進行破壞。一個小例子是一個Expr類型,它有2個成員IntConst int和IntMutable int。 – maattdd

+2

但是必須有某個其他標誌(包含'struct'或'class')指示哪個聯合成員是_active_?這可以用來提供額外的必要含義。 – hmjd

回答

5

如果你想做到這一點,我想你最好的選擇是包裝相同,但是,不同類型成一個結構,然後讓升壓變訪問正確的一個:

struct Speed 
{ 
    float val_; 
}; 

struct Darkness 
{ 
    float val_; 
}; 

可能能夠使用BOOST_STRONG_TYPEDEF自動執行此操作,但我不確定它是否能夠生成合法使用的類型(儘管在變體中它可能沒問題)。

2

的C++代碼在這裏:

http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_storage/pack/container_one_of_maybe.hpp

是真正的,因爲它可以包含重複類型的一個標籤聯合。一個不錯的功能 是標籤可以枚舉;因此,標籤可以具有有意義的名稱。

不幸的是,編譯時間成本非常糟糕,我想,因爲實現 使用遞歸繼承。 OTOH,也許編譯器最終會找出一種方法來減少編譯時間成本。

OTOH,如果你想堅持使用boost :: variant,你可以按照Mark B的建議包裝 。但是,代替Mark B的描述性類名稱 需要一些考慮,您可以使用fusion::pair<mpl::int_<tag>,T_tag> 其中T_tag是源fusion::vector中的第個元素。督察:

variant 
< fusion::pair<mpl::int_<1>,T1> 
, fusion::pair<mpl::int_<2>,T2> 
... 
, fusion::pair<mpl::int_<n>,Tn> 
> 

由於融合文檔:

http://www.boost.org/doc/libs/1_55_0/libs/fusion/doc/html/fusion/support/pair.html

說,fusion::pair只分配了第二個模板參數空間;因此, 這應該不會比boost::variant<T1,T2,...,Tn>佔用更多空間。

HTH。

-regards, 拉里

1

你不能在此刻卻C++17's implementation of std::variant還好允許它:

一個變體被允許持有相同類型不止一次,並持有不同品種合格相同類型的版本。

不像增壓版本,您可以通過索引獲取值,像這樣(未測試):

// Construct a variant with the second value set. 
variant<string, string, string> s(std::in_place_index<1>, "Hello"); 
// Get the second value. 
string first = std::get<1>(s); 

邁克爾公園寫a C++14 implementation of C++17's std::variant

相關問題