亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++17之std::any的具體使用

 更新時(shí)間:2022年02月07日 09:57:45   作者:云洞  
本文主要介紹了C++17之std::any的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

    一般來(lái)說(shuō),c++是一種具有類型綁定和類型安全性的語(yǔ)言。值對(duì)象聲明為具有特定類型,該類型定義哪些操作是可能的以及它們的行為方式。值對(duì)象不能改變它們的類型。

    std: any是一種值類型,它能夠更改其類型,同時(shí)仍然具有類型安全性。也就是說(shuō),對(duì)象可以保存任意類型的值,但是它們知道當(dāng)前保存的值是哪種類型。在聲明此類型的對(duì)象時(shí),不需要指定可能的類型。

    訣竅在于,對(duì)象同時(shí)擁有包含的值和使用typeid包含值的類型。因?yàn)檫@個(gè)值可以有任何大小,所以可以在堆上分配內(nèi)存,鼓勵(lì)實(shí)現(xiàn)避免小對(duì)象的動(dòng)態(tài)分配。也就是說(shuō),如果分配一個(gè)字符串,對(duì)象將為該值分配內(nèi)存并復(fù)制該字符串,同時(shí)也在內(nèi)部存儲(chǔ)分配的字符串。稍后,可以執(zhí)行運(yùn)行時(shí)檢查來(lái)確定當(dāng)前值的類型,并使用any_cast<該值的類型>獲取值。

1. 使用std::any

下面的例子演示了std::any:

std::any a; // a is empty
std::any b = 4.3; // b has value 4.3 of type double
 
a = 42; // a has value 42 of type int
b = std::string{"hi"}; // b has value "hi" of type std::string
 
if (a.type() == typeid(std::string)) 
{
    std::string s = std::any_cast<std::string>(a);
    useString(s);
}
else if (a.type() == typeid(int)) 
{
    useInt(std::any_cast<int>(a));
}

    可以聲明std::any為空或由特定類型的值初始化。初始值的類型成為所包含值的類型。通過(guò)使用成員函數(shù)type(),可以根據(jù)任何類型的類型ID檢查所包含值的類型。如果對(duì)象是空的,對(duì)象類型ID是typeid(void)。要訪問(wèn)包含的值,可以通過(guò)std::any_cast<對(duì)象類型>的方式:

auto s = std::any_cast<std::string>(a);

如果轉(zhuǎn)換失敗,因?yàn)閷?duì)象為空或包含的類型不匹配,則拋出std::bad_any_cast。因此,在不檢查或不知道類型的情況下,最好實(shí)現(xiàn)以下功能:

try {
auto s = std::any_cast<std::string>(a);
...
}
catch (std::bad_any_cast& e) {
std::cerr << "EXCEPTION: " << e.what() << '\n';
}

注意,std::any_cast<>創(chuàng)建了一個(gè)傳遞類型的對(duì)象。如果將std::string作為模板參數(shù)傳遞給std::any_cast<>,它將創(chuàng)建一個(gè)臨時(shí)string(一個(gè)prvalue),然后用它初始化新對(duì)象s。如果沒(méi)有這樣的初始化,通常最好轉(zhuǎn)換為引用類型,以避免創(chuàng)建臨時(shí)對(duì)象:

std::cout << std::any_cast<const std::string&>(a);

要修改該值,需要轉(zhuǎn)換為對(duì)應(yīng)的引用類型:

std::any_cast<std::string&>(a) = "world";

還可以為std::any對(duì)象的地址調(diào)用std::any_cast。在這種情況下,如果類型匹配,則強(qiáng)制轉(zhuǎn)換返回相應(yīng)的地址指針;如果不匹配,則返回nullptr:

auto p = std::any_cast<std::string>(&a);
if (p) {
...
}

例1:

#include <iostream>
#include <any>
 
int main()
{
    std::any i = 42;
    const auto ptr = std::any_cast<int>(&i);
    if (ptr)
    {
        std::cout << ptr << std::endl;
    }
 
    return 0;
}

結(jié)果如下:

要清空現(xiàn)有std::任何可以調(diào)用的對(duì)象:

方法1:a.reset(); // makes it empty

方法2:a = std::any{};

方法3: a = {};

可以直接檢查對(duì)象是否為空:

if (a.has_value()) {
...
}

還要注意,值是使用衰減類型存儲(chǔ)的(數(shù)組轉(zhuǎn)換為指針,忽略頂層引用和const)。對(duì)于字符串常量,這意味著值類型是const char*。要檢查type()并使用std::any_cast<>,必須使用以下類型:

std::any a = "hello"; // type() is const char*
if (a.type() == typeid(const char*)) { // true
...
}
if (a.type() == typeid(std::string)) { // false
...
}
std::cout << std::any_cast<const char*>(v[1]) << '\n'; // OK
std::cout << std::any_cast<std::string>(v[1]) << '\n'; // EXCEPTION

    std::any沒(méi)有定義比較運(yùn)算符(因此,不能比較或排序?qū)ο?,沒(méi)有定義hash函數(shù),也沒(méi)有定義value()成員函數(shù)。由于類型只在運(yùn)行時(shí)才知道,所以不能使用泛型lambdas處理與類型無(wú)關(guān)的當(dāng)前值。總是需要運(yùn)行時(shí)函數(shù)std::any_cast<>來(lái)處理當(dāng)前值。

    然而,可以將std::任何對(duì)象放入容器中。

例2:

#include <iostream>
#include <vector>
#include <any>
 
int main()
{
    std::vector<std::any> v;
    v.push_back(42);
    std::string s = "hello";
    v.push_back(s);
    for (const auto& a : v) {
        if (a.type() == typeid(std::string)) {
            std::cout << "string: " << std::any_cast<const std::string&>(a) << '\n';
        }
        else if (a.type() == typeid(int)) {
            std::cout << "int: " << std::any_cast<int>(a) << '\n';
        }
    }
}

結(jié)果如下:

 2. std::any類型和操作

本節(jié)詳細(xì)描述std::any的類型和操作。

2.1 std::any的類型

在頭文件<any>中,c++標(biāo)準(zhǔn)庫(kù)定義了類std::any,如下所示:

namespace std {
class any;
}

也就是說(shuō),std::any根本不是類模板。

此外,定義了以下類型和對(duì)象:

如果類型轉(zhuǎn)換失敗,則拋出異常類型std::bad_any_cast,它派生自std::bad_cast,而std::bad_cast派生自std::exception。

any對(duì)象還可以使用<utility>中定義的對(duì)象std::in_place_type(類型為std::in_place_type_t)。

2.2 std::any操作

std::any操作

std::any操作
函數(shù)說(shuō)明
constructors創(chuàng)建一個(gè)any對(duì)象(可能調(diào)用底層類型的構(gòu)造函數(shù))
make_any()創(chuàng)建一個(gè)any對(duì)象(傳遞值來(lái)初始化它)
destructor銷毀any對(duì)象
=分配一個(gè)新值
emplace<T>()分配一個(gè)類型為T的新值
reset()銷毀any對(duì)象的值(使對(duì)象為空)
has_value()返回對(duì)象是否具有值
type()返回當(dāng)前類型為std::type_info對(duì)象
any_cast<T>()使用當(dāng)前值作為類型T的值(如果其他類型除外)
swap()交換兩個(gè)any對(duì)象的值
  

1. 構(gòu)造函數(shù)

默認(rèn)情況下,std::any的初始值為空。

std::any a1; // a1 is empty

如果傳遞一個(gè)值進(jìn)行初始化,則將其衰減類型用作所包含值的類型:

std::any a2 = 42; // a2 contains value of type int
std::any a3 = "hello"; // a2 contains value of type const char*

要保存與初始值類型不同的類型,必須使用in_place_type標(biāo)記:

std::any a4{std::in_place_type<long>, 42};
std::any a5{std::in_place_type<std::string>, "hello"};

即使傳遞給in_place_type的類型也會(huì)衰減。下面的聲明包含一個(gè)const char*:

std::any a5b{std::in_place_type<const char[6]>, "hello"};

要通過(guò)多個(gè)參數(shù)初始化可選對(duì)象,必須創(chuàng)建該對(duì)象或?qū)td::in_place_type添加為第一個(gè)參數(shù)(不能推斷包含的類型):

std::any a6{std::complex{3.0, 4.0}};
std::any a7{std::in_place_type<std::complex<double>>, 3.0, 4.0};

甚至可以傳遞一個(gè)初始化器列表,后面跟著附加的參數(shù):

// initialize a std::any with a set with lambda as sorting criterion:
auto sc = [] (int x, int y) { return std::abs(x) < std::abs(y);};
 
std::any a8{std::in_place_type<std::set<int,decltype(sc)>>, {4, 8, -7, -2, 0, 5}, sc};

注意,還有一個(gè)方便的函數(shù)make_any<>(),它可以用于單個(gè)或多個(gè)參數(shù)(不需要in_place_type參數(shù))。必須顯式指定初始化的類型(如果只傳遞一個(gè)參數(shù),則不會(huì)推導(dǎo)出初始化的類型):

auto a10 = std::make_any<float>(3.0);
auto a11 = std::make_any<std::string>("hello");
auto a13 = std::make_any<std::complex<double>>(3.0, 4.0);
auto a14 = std::make_any<std::set<int,decltype(sc)>>({4, 8, -7, -2, 0, 5}, sc);

2. 訪問(wèn)值

要訪問(wèn)包含的值,必須使用std::any_cast<>將其轉(zhuǎn)換為其類型。將該值轉(zhuǎn)換為一個(gè)字符串,有幾個(gè)選項(xiàng):

std::any_cast<std::string>(a) // yield copy of the value
std::any_cast<std::string&>(a); // write value by reference
std::any_cast<const std::string&>(a); // read-access by reference

在這里,如果轉(zhuǎn)換失敗,將拋出std::bad_any_cast異常。

如果把std::any中所包含的類型轉(zhuǎn)換為移除了傳遞類型的頂層引用后的類型ID,則轉(zhuǎn)換類型是適合的。如下:

#include <iostream>
#include <string>
#include <any>
 
int main()
{
    const auto& s = std::make_any<std::string>("hello");
    
    if (s.type() == typeid(std::string))//刪除頂層cosnt和引用后的類型
    {
        auto a = std::any_cast<std::string>(s);
        std::cout << a << std::endl;
    }
 
    return 0;
}

結(jié)果如下:

如果類型不匹配轉(zhuǎn)換失敗了,傳遞一個(gè)地址將會(huì)返回nullptr:

auto a = std::make_any<std::string>("hello");
std::any_cast<std::string>(&a) // write-access via pointer
std::any_cast<const std::string>(&a); // read-access via pointer

注意,這里轉(zhuǎn)換到引用會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤:

std::any_cast<std::string&>(&a); // RUN-TIME ERROR

3. 修改值

相應(yīng)的賦值和emplace()操作。例如:

#include <iostream>
#include <string>
#include <any>
#include <complex>
 
int main()
{
    std::any a;
    a = 42; // a contains value of type int
    a = "hello"; // a contains value of type const char*
 
    a.emplace<std::string>("hello world");// a contains value of type std::string
 
    return 0;
}

結(jié)果如下:

4. 移動(dòng)語(yǔ)法 

    std: any也支持移動(dòng)語(yǔ)義。但是,請(qǐng)注意,move語(yǔ)義必須滿足包含的類型具有可復(fù)制構(gòu)造函數(shù)。也就是說(shuō),不支持只移動(dòng)類型作為包含值類型。處理move語(yǔ)義的最佳方法可能并不明顯。所以,你應(yīng)該這樣做:

std::string s("hello, world!");
std::any a;
a = std::move(s); // move s into a
s = std::move(std::any_cast<string&>(a)); // move assign string in a to s

 與通常的從對(duì)象移動(dòng)的情況一樣,在最后一次調(diào)用之后,所包含的值a是未指定的。因此,可以使用a作為字符串,只要沒(méi)有對(duì)所包含的字符串值的值做任何假設(shè)。

注意:

s = std::any_cast<string>(std::move(a));

也可以,但需要一個(gè)額外的移動(dòng)。然而,以下內(nèi)容是危險(xiǎn)的(盡管它是c++標(biāo)準(zhǔn)中的一個(gè)例子):

std::any_cast<string&>(a) = std::move(s2); // OOPS: a to hold a string

只有當(dāng)包含的值已經(jīng)是字符串時(shí),才可以這樣做。如果沒(méi)有,轉(zhuǎn)換將拋出一個(gè)std::bad_any_cast異常。

到此這篇關(guān)于C++17之std::any的具體使用的文章就介紹到這了,更多相關(guān)C++17 std::any內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C/C++實(shí)現(xiàn)馬踏棋盤算法

    C/C++實(shí)現(xiàn)馬踏棋盤算法

    這篇文章主要為大家詳細(xì)介紹了C/C++實(shí)現(xiàn)馬踏棋盤算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C語(yǔ)言八皇后問(wèn)題解決方法示例【暴力法與回溯法】

    C語(yǔ)言八皇后問(wèn)題解決方法示例【暴力法與回溯法】

    這篇文章主要介紹了C語(yǔ)言八皇后問(wèn)題解決方法,簡(jiǎn)單描述了八皇后問(wèn)題并結(jié)合實(shí)例形式分析了C語(yǔ)言基于暴力法與回溯法解決八皇后的具體操作技巧,需要的朋友可以參考下
    2018-01-01
  • 基于Matlab制作偽3D第一視角迷宮小游戲

    基于Matlab制作偽3D第一視角迷宮小游戲

    這篇文章主要為大家詳細(xì)介紹了如何利用Matlab語(yǔ)言制作偽3D第一視角迷宮小游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下
    2022-07-07
  • C++實(shí)現(xiàn)俄羅斯方塊源碼

    C++實(shí)現(xiàn)俄羅斯方塊源碼

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)俄羅斯方塊源碼完整版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Windows 環(huán)境下使用 Qt 連接 MySQL

    Windows 環(huán)境下使用 Qt 連接 MySQL

    這篇文章主要介紹了Windows 環(huán)境下使用 Qt 連接 MySQL的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • C++中如何實(shí)現(xiàn)回調(diào)的方法示例

    C++中如何實(shí)現(xiàn)回調(diào)的方法示例

    這篇文章主要給大家介紹了關(guān)于C++中如何實(shí)現(xiàn)回調(diào)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • C++中的常量定義小結(jié)

    C++中的常量定義小結(jié)

    在C++中,并不提倡使用#define定義一個(gè)常量。#define本質(zhì)上是一個(gè)預(yù)處理器指令,它僅僅表示使用一個(gè)串代替別一個(gè)串而已。也就是說(shuō),#define定義的常量從未被編譯器看到——它們?cè)诰幾g器開(kāi)始處理源碼之前就被移走了
    2015-08-08
  • OpenCV提取圖像中圓線上的數(shù)據(jù)具體流程

    OpenCV提取圖像中圓線上的數(shù)據(jù)具體流程

    在對(duì)圖像進(jìn)行處理時(shí),經(jīng)常會(huì)要提取出圖像中某條直線、圓線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點(diǎn)關(guān)注。本文主要介紹了利用OpenCV獲取圖像中圓線上的數(shù)據(jù),需要的可以參考一下
    2021-11-11
  • C/C++ 運(yùn)用Npcap發(fā)送UDP數(shù)據(jù)包的完美過(guò)程

    C/C++ 運(yùn)用Npcap發(fā)送UDP數(shù)據(jù)包的完美過(guò)程

    UDP 是一種無(wú)連接、輕量級(jí)的傳輸層協(xié)議,與 TCP 相比,它不提供可靠性、流控制和錯(cuò)誤恢復(fù)機(jī)制,但卻更加簡(jiǎn)單且具有較低的開(kāi)銷,這篇文章主要介紹了C/C++ 運(yùn)用Npcap發(fā)送UDP數(shù)據(jù)包,需要的朋友可以參考下
    2023-11-11
  • 淺談關(guān)于C++memory_order的理解

    淺談關(guān)于C++memory_order的理解

    這篇文章主要介紹了淺談關(guān)于C++memory_order的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評(píng)論