zoukankan      html  css  js  c++  java
  • C++ boost::variant

    今天看代码时候发现用了variant,第一次接触这个类,没想到C++还有这种类,

    前言

    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官网

    转自:https://www.cnblogs.com/highway-9/p/6002306.html

    诸位正值青春年少,一定恣情放纵,贪恋香艳梅施之情,喜欢风流雅韵之事,洒脱木拘。然而诸位可知,草上露一碰即落,竹上霜一触即溶,此种风情难于长久。
  • 相关阅读:
    Centos7 yum 安装 oracle-rdbms-server-11gR2-pre
    R语言 小程序
    Hadoop! | 大数据百科 | 数据观 | 中国大数据产业观察_大数据门户
    【R】如何确定最适合数据集的机器学习算法
    R语言 recommenderlab 包
    R语言 推荐算法 recommenderlab包
    R语言进行数据预处理wranging
    统计学 nested_design 嵌套设计
    [LeetCode] 160. 相交链表
    [LeetCode] 155. 最小栈
  • 原文地址:https://www.cnblogs.com/shilipojianshen/p/13372171.html
Copyright © 2011-2022 走看看