美文网首页
C++17:std::any, std::variant 和 s

C++17:std::any, std::variant 和 s

作者: fck_13 | 来源:发表于2020-01-21 01:00 被阅读0次

    莫名的觉得这三个类好像,所以就放在一块学习一下,感觉就是一个代表很多类型的类。

    • std::any
      一个类型安全的容器,可以放置各种类型的数据。
    #include <any>
    #include <iostream>
    
    int main()
    {
      std::cout << std::boolalpha; //将bool值用 "true" 和 "false"显示
      std::any a;  //定义一个空的any,即一个空的容器
      //有两种方法来判断一个any是否是空的
      std << cout << a.has_value() <<std::endl; // any是空的时,has_value 返回值为 false
      std << cout << a.type().name() <<std::endl; //any 是空的时,has_value 返回值为 true
      //几种创建any的方式
      std::any b = 1;                         //b 为存了int类型的值的any
      auto c = std::make_any<float>(5.0f);    //c为存了float类型的any
      std::any d(6.0);                        //d为存储了double类型的any
      std << cout << b.has_value() <<std::endl;   //true 
      std << cout << b.type().name() <<std::endl; //int
      std << cout << c.has_value() <<std::endl;   //true
      std << cout << c.type().name() <<std::endl; //float
      std << cout << d.has_value() <<std::endl;   //true
      std << cout << d.type().name() <<std::endl; //double
      
      //更改any的值    
      a = 2;   //直接重新赋值
      auto e = c.emplace<float>(4.0f); //调用emplace函数,e为新生成的对象引用
    
      //清空any的值
      b.reset();
      std << cout << b.has_value() <<std::endl;   //false
      std << cout << b.type().name() <<std::endl; //int
    
      //使用any的值
      try
      {
        auto f = std::any_cast<int>(a); //f为int类型,其值为2
        std::cout << f <<std::endl; //2
      }
      catch(const std::bad_any_cast& e)
      {
        std::cout<< e.what()<<std::endl;
      }
    
      try
      {
        auto g = std::any_cast<float>(a); //抛出std::bad_any_cat 异常
        std::cout << g <<std::endl; //该语句不会执行
      }
      catch(const std::bad_any_cast& e)
      {
        std::cout<< e.what()<<std::endl;  //可能输出Bad any_cast
      }
      return 0;
    
    • std::variant
      std::variant是类型安全的union
    
    #include <variant>
    #include <iostream>
    
    union my_union
    {
        int i;
        float f;
        char c;
    };
    
    int main()
    {
        std::cout << std::boolalpha;
        std::variant<int, float, char> variant;
        //这里的variant等价于my_union
        
        //在构造的时候,如果构造过程中抛出了异常,valueless_by_exception的返回值为true
        std::cout<< variant.valueless_by_exception()<<std::endl;   //false
    
        {
            variant = 12;   // variant包含了int类型
            int i = std::get<int>(variant);  //使用std::get<T>可以获取所含有的值
    
            try
            {
                auto f = std::get<float>(variant);  //此时的值为int,所以想要获取float的时候就会抛出异常
            }
            catch (const std::bad_variant_access & exception)
            {
                std::cout << exception.what() << std::endl;
            }
    
            variant = 1.0f;
            auto f = std::get<float>(variant);
            std::cout << f << std::endl;  //1.0
        }
        
    
        {
            //还可以使用索引来获取对应的值
            auto f = std::get<1>(variant);  
            try
            {
                auto i = std::get<0>(variant);
            }
            catch (const std::bad_variant_access & exception)
            {
                std::cout << exception.what() << std::endl;
            }
    
            variant = 1;
            auto i = std::get<0>(variant);
            std::cout<<i<<std::endl;  //1
        }
    
        variant = 2.0f;
        std::cout << variant.index() << std::endl;  //1
    
        variant = 2;
        std::cout << variant.index() << std::endl;  //0
    
        return 0;
    }
    
    • std::optional
      该类型是用来表示一个值是不是存在的。std::optional有两个状态,即有值和无值。通常我们将std::optional用于函数的返回值,当函数执行成功了返回有值的状态,当函数执行失败了返回无值的状态。当std::optional有值时,它可以在使用bool值的地方转化为true,反之,转化为false
    #include <iostream>
    #include <optional>
    
    int main()
    {
        std::cout << std::boolalpha;
        std::optional<int> op1;       //表示一个不存在的值
        std::optional<int> op2 = 1;   //表示一个存在的int类型的值
        std::optional<int> op3(2);    //表示存在的一个int类型的值
        std::optional<std::string> op4(std::in_place, 3, 'A');     //构建一个存有std::string类型的std::optional,
                                                                   //调用std::string的构造函数,其值为"AAA"
        
        std::cout << op1.has_value() << std::endl;   //输出为false
        
        if (!op1)    
        {
            std::cout << "empty optional is false" << std::endl;  //由于op1不存在值,所以在此转化为false
        }
    
        try 
        {
            std::cout << op4.value() << std::endl;     //获取std::optional 的值,如果不存在值,则抛出std::bad_optional_access异常
        }
        catch (std::bad_optional_access & e)
        {
            std::cout << e.what() << std::endl;
        }
    
        std::optional<int> op5;
        std::cout<<op5.value_or(5)<<std::endl;
    
        op2.reset();
        std::cout << op2.has_value() << std::endl; //false
    
        op2 = 3;
        op2 = 4.0;
        std::cout << op2.value() << std::endl;    //4.0
        
        op2.emplace<int>(5);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:C++17:std::any, std::variant 和 s

          本文链接:https://www.haomeiwen.com/subject/rifszctx.html