2010-06-20 35 views
2
struct A 
    { 
    std::string get_string(); 
    }; 

    struct B 
    { 
    int value; 
    }; 

    typedef boost::variant<A,B> var_types; 
    std::vector<var_types> v; 

    A a; 
    B b; 

    v.push_back(a); 
    v.push_back(b); 

如何迭代迭代遍歷v的元素以訪問a和b對象?如何使用Boost.Variant遍歷有界類型的序列

我能夠用升壓做到這一點::得到,但語法真的是很麻煩:

std::vector<var_types>:: it = v.begin(); 
while(it != v.end()) 
{ 
    if(A* temp_object = boost::get<A>(&(*it)))  
     std::cout << temp_object->get_string(); 
    ++it; 
} 

我試圖使用探視的技術,但我沒有得到太遠和代碼不工作:

template<typename Type> 
class get_object 
    : public boost::static_visitor<Type> 
{ 
public: 

    Type operator()(Type & i) const 
    { 
    return i; 
    } 

}; 

... 

while(it != v.end()) 
{ 
    A temp_object = boost::apply_visitor(get_object<A>(),*it); 
    ++it; 
} 

EDIT 1

甲hackish的解決方案是:

class get_object 
    : public boost::static_visitor<A> 
{ 
public: 

    A operator()(const A & i) const 
    { 
    return i; 
    } 

    A operator()(const B& i) const 
    { 
    return A(); 
    }   
}; 
+0

所以要通過對象和用於依賴於如果所述變體保持的A或B中的每個元件呼叫任一函數X或Y來迭代? – GManNickG 2010-06-20 05:21:56

+0

是的,非常多:) – anno 2010-06-20 05:35:20

回答

1

編輯:
如果它是作爲UncleBens建議,那麼你可以簡單地這樣做:

BOOST_FOREACH(var_types& vt, v) { 
    if (vt.which() == 0) 
     cout << get<A>(vt).get_string() << endl; 
} 

原文:
static_vistor模板參數是其方法的返回類型。這意味着兩個類需要爲單個訪問者共享一個共同的返回類型。它應該看起來像這樣:

class ABVisitor : public static_visitor<string> { 
public: 
    string operator()(const A& a) const { 
     return a.get_string(); 
    } 
    string operator()(const B& b) const { 
     return lexical_cast<string>(b.value); 
    } 
}; 

下面是使用此訪問者進行迭代的示例。

BOOST_FOREACH(var_types& vt, v) 
    cout << apply_visitor(ABVisitor(), vt) << endl; 
+0

但是,這並不總是輸出一些東西,而在最初的嘗試中,只有當對象是A時纔打印出東西? – UncleBens 2010-06-20 09:46:39

+0

@UncleBens:你說得對。 for循環的整個機構應該在這次訪問中。 – 2010-06-20 10:48:01

+0

正如我所說,我知道如何去做,但如果我必須通過類接口公開它,語法非常不友好。 – anno 2010-06-21 03:59:44

3

據我所知,訪客應該做這項工作。如果你只是想獲得儲值,那麼boost::get - 如果我沒有弄錯 - 預先製作的訪問者。

實施例:

struct print_if_a : boost::static_visitor<void> 
    { 
    void operator()(A& a) const { std::cout << a.get_string() << '\n'; } //alas, get_string is non-const 
    void operator()(const B&) const {} //does nothing, up to optimizer 
    }; 

用法:

BOOST_FOREACH(var_types& obj, v) { 
    boost::apply_visitor(print_if_a(), obj); 
    } 
+0

這裏沒有必要精確地確定'boost :: static_visitor'的返回類型,如果我沒有弄錯,它默認爲'void'。 – 2010-06-20 10:47:21

+0

@Matthieu:是的,你也可以寫'boost :: static_visitor <>'。 – UncleBens 2010-06-20 11:40:41