淺談boost.variant的幾種訪問方式


此處輸入圖片的描述

前言

variant類型在C++14並沒有加入,在cppreference網站上可以看到該類型將會在C++17加入,若想在不支持C++17的編譯器上使用variant類型,我們可以通過boost的variant類型,variant類型可以表示任意一種類型和any類型有些相似,但還是有些區別,比如說variant支持的類型需提前定義,而any類型不需要,獲取any類型的值需要給出原始類型,然而variant類型支持多種方式訪問,其中一種就是通過訪問者模式來訪問,是不需要給出原始類型的,下面將淺談variant的幾種訪問方式(個人博客也發表了《淺談boost.variant的幾種訪問方式》)。

使用boost::get

boost::variant<int, std::string> v;
v = "Hello world";
std::cout << boost::get<std::string>(v) << std::endl;

使用boost::get來訪問,需要給出原始類型,並且這樣做不安全,若類型錯誤,程序將會拋出異常。

使用RTTI

void var_print(boost::variant<int, std::string>& v)  
{  
    if (v.type() == typeid(int))  
    {  
        std::cout << boost::get<int>(v) << std::endl;  
    }
    else if (v.type() == typeid(std::string))  
    {  
        std::cout << boost::get<std::string>(v) << std::endl;  
    }  
    // Else do nothing
}  
int main()  
{  
    boost::variant<int, std::string> v;
    v = "Hello world";  
    var_print(v);
    return 0;
}  

使用RTTI技術可以避免類型訪問錯誤而程序異常的情況,但是這樣做有點不優雅,每增加一個類型,都需要修改if-else結構,並且使用RTTI會對程序性能有一定影響。

使用訪問者模式

class var_visitor : public boost::static_visitor<void>
{
public:
    void operator()(int& i) const
    {
        std::cout << i << std::endl;
    }

    void operator()(std::string& str) const
    {
        std::cout << str << std::endl;
    }
};
int main()  
{  
    boost::variant<int, std::string> v;
    v = "Hello world";  
    boost::apply_visitor(var_visitor(), v);
    return 0;
} 

使用該模式,需要定義一個類並繼承於boost::static_visitor,在類里面需要重載()操作符,通過boost::apply_visitor來訪問原始類型的值,這樣做還是有些繁瑣,每增加一個類型,都需要在var_visitor里面增加一個函數,但比使用RTTI里面的修改if-else結構好得多,因為使用訪問者模式至少是遵循開放-封閉原則的,即對寫開放,對修改封閉。

使用模板函數

class var_visitor : public boost::static_visitor<void>
{
public:
    template<typename T>
    void operator()(T& i) const
    {
        std::cout << i << std::endl;
    }
};
int main()  
{  
    boost::variant<int, std::string> v;
    v = "Hello world";  
    boost::apply_visitor(var_visitor(), v);
    return 0;
} 

operator()改成了模板函數的好處就是不用關心variant支持多少類型。

參考資料

boost官網


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM