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

莫名的覺得這三個類好像,所以就放在一塊學(xué)習(xí)一下,感覺就是一個代表很多類型的類。

  • std::any
    一個類型安全的容器,可以放置各種類型的數(shù)據(jù)。
#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
  //幾種創(chuàng)建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); //調(diào)用emplace函數(shù),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; //該語句不會執(zhí)行
  }
  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
    
    //在構(gòu)造的時候,如果構(gòu)造過程中拋出了異常,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
    }
    

    {
        //還可以使用索引來獲取對應(yīng)的值
        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有兩個狀態(tài),即有值和無值。通常我們將std::optional用于函數(shù)的返回值,當(dāng)函數(shù)執(zhí)行成功了返回有值的狀態(tài),當(dāng)函數(shù)執(zhí)行失敗了返回?zé)o值的狀態(tài)。當(dāng)std::optional有值時,它可以在使用bool值的地方轉(zhuǎn)化為true,反之,轉(zhuǎn)化為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');     //構(gòu)建一個存有std::string類型的std::optional,
                                                               //調(diào)用std::string的構(gòu)造函數(shù),其值為"AAA"
    
    std::cout << op1.has_value() << std::endl;   //輸出為false
    
    if (!op1)    
    {
        std::cout << "empty optional is false" << std::endl;  //由于op1不存在值,所以在此轉(zhuǎn)化為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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容