日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

掌握C++模板的藝術:類型參數、默認值和自動推導

來源: 責編: 時間:2023-12-14 16:37:59 229觀看
導讀一、模板參數1.類型模板參數在 Grid 示例中,Grid 模板有一個模板參數:存儲在網格中的類型。編寫類模板時,您需要在尖括號內指定參數列表,例如:template <typename T>這個參數列表類似于函數或方法中的參數列表。與函數和方

FPr28資訊網——每日最新資訊28at.com

一、模板參數

1.類型模板參數

在 Grid 示例中,Grid 模板有一個模板參數:存儲在網格中的類型。編寫類模板時,您需要在尖括號內指定參數列表,例如:FPr28資訊網——每日最新資訊28at.com

template <typename T>

這個參數列表類似于函數或方法中的參數列表。與函數和方法一樣,你可以編寫具有任意多個模板參數的類。此外,這些參數不必是類型,它們可以有默認值。FPr28資訊網——每日最新資訊28at.com

2.非類型模板參數

非類型參數是普通參數,如整數和指針——這類參數你可能已經在函數和方法中很熟悉了。然而,非類型模板參數只能是整型(char、int、long 等)、枚舉類型、指針、引用、std::nullptr_t、auto、auto& 和 auto*。C++20 還允許浮點類型和類類型的非類型模板參數。后者有很多限制,在本文中不再詳細討論。FPr28資訊網——每日最新資訊28at.com

在 Grid 類模板中,你可以使用非類型模板參數來指定網格的高度和寬度,而不是在構造函數中指定。在模板列表中指定非類型參數而不是在構造函數中指定的主要優點是這些值在代碼編譯之前就已知。回想一下,編譯器通過在編譯之前替換模板參數來生成模板實例的代碼。因此,你可以在實現中使用普通的二維數組,而不是動態調整大小的向量數組。以下是帶有更改的新類定義:FPr28資訊網——每日最新資訊28at.com

export template <typename T, size_t WIDTH, size_t HEIGHT>class Grid {public:    Grid() = default;    virtual ~Grid() = default;    // 明確默認復制構造函數和賦值運算符。    Grid(const Grid& src) = default;    Grid& operator=(const Grid& rhs) = default;    std::optional<T>& at(size_t x, size_t y);    const std::optional<T>& at(size_t x, size_t y) const;    size_t getHeight() const { return HEIGHT; }    size_t getWidth() const { return WIDTH; }private:    void verifyCoordinate(size_t x, size_t y) const;    std::optional<T> m_cells[WIDTH][HEIGHT];};

注意,模板參數列表需要三個參數:存儲在網格中的對象類型,以及網格的寬度和高度。寬度和高度用于創建存儲對象的二維數組。下面是類方法的定義:FPr28資訊網——每日最新資訊28at.com

// 類方法定義template <typename T, size_t WIDTH, size_t HEIGHT>void Grid<T, WIDTH, HEIGHT>::verifyCoordinate(size_t x, size_t y) const {    if (x >= WIDTH) {        throw std::out_of_range { std::format("{} must be less than {}.", x, WIDTH) };    }    if (y >= HEIGHT) {        throw std::out_of_range { std::format("{} must be less than {}.", y, HEIGHT) };    }}template <typename T, size_t WIDTH, size_t HEIGHT>const std::optional<T>& Grid<T, WIDTH, HEIGHT>::at(size_t x, size_t y) const {    verifyCoordinate(x, y);    return m_cells[x][y];}template <typename T, size_t WIDTH, size_t HEIGHT>std::optional<T>& Grid<T, WIDTH, HEIGHT>::at(size_t x, size_t y) {    return const_cast<std::optional<T>&>(std::as_const(*this).at(x, y));}

注意,之前你在哪里指定了 Grid<T>,現在你必須指定 Grid<T, WIDTH, HEIGHT> 來指定三個模板參數。你可以這樣實例化并使用這個模板:FPr28資訊網——每日最新資訊28at.com

Grid<int, 10, 10> myGrid;Grid<int, 10, 10> anotherGrid;myGrid.at(2, 3) = 42;anotherGrid = myGrid;cout << anotherGrid.at(2, 3).value_or(0);

這段代碼看起來很棒,但不幸的是,存在比你最初預期的更多限制。首先,你不能使用非常量整數來指定高度或寬度。以下代碼無法編譯:FPr28資訊網——每日最新資訊28at.com

size_t height { 10 };Grid<int, 10, height> testGrid; // 無法編譯

然而,如果你將高度定義為常量,則可以編譯:FPr28資訊網——每日最新資訊28at.com

const size_t height { 10 };Grid<int, 10, height> testGrid; // 可編譯并工作

具有正確返回類型的 constexpr 函數也可以工作。例如,如果你有一個返回 size_t 的 constexpr 函數,你可以用它來初始化高度模板參數:FPr28資訊網——每日最新資訊28at.com

constexpr size_t getHeight() { return 10; }...Grid<double, 2, getHeight()> myDoubleGrid;

第二個限制可能更重要?,F在寬度和高度是模板參數,它們是每個網格類型的一部分。這意味著 Grid<int,10,10> 和 Grid<int,10,11> 是兩種不同的類型。你不能將一種類型的對象賦值給另一種類型的對象,也不能將一種類型的變量傳遞給期望另一種類型變量的函數或方法。FPr28資訊網——每日最新資訊28at.com

注意:非類型模板參數成為實例化對象類型規范的一部分。FPr28資訊網——每日最新資訊28at.com

二、類模板參數的默認值

設置高度和寬度的默認值

如果您繼續使用高度和寬度作為模板參數的方法,您可能想為 Grid<T> 類構造函數中之前的高度和寬度非類型模板參數提供默認值。C++ 允許您使用類似的語法為模板參數提供默認值。同時,您也可以為 T 類型參數提供默認值。下面是類定義:FPr28資訊網——每日最新資訊28at.com

export template <typename T = int, size_t WIDTH = 10, size_t HEIGHT = 10>class Grid {    // 其余部分與之前版本相同};

在方法定義的模板規范中,您不需要為 T、WIDTH 和 HEIGHT 指定默認值。例如,這是 at() 方法的實現:FPr28資訊網——每日最新資訊28at.com

template <typename T, size_t WIDTH, size_t HEIGHT>const std::optional<T>& Grid<T, WIDTH, HEIGHT>::at(size_t x, size_t y) const {    verifyCoordinate(x, y);    return m_cells[x][y];}

現在,您可以在沒有任何模板參數的情況下實例化 Grid,只需指定元素類型,元素類型和寬度,或元素類型、寬度和高度:FPr28資訊網——每日最新資訊28at.com

Grid<> myIntGrid;Grid<int> myGrid;Grid<int, 5> anotherGrid;Grid<int, 5, 5> aFourthGrid;

請注意,如果您不指定任何類模板參數,您仍然需要指定一組空的尖括號。例如,以下代碼無法編譯!FPr28資訊網——每日最新資訊28at.com

Grid myIntGrid;

類模板參數列表中默認參數的規則與函數或方法相同;也就是說,您可以從右邊開始為參數提供默認值。FPr28資訊網——每日最新資訊28at.com

三、類模板參數推導(CTAD)

1.自動推導模板參數

類模板參數推導允許編譯器自動從傳遞給類模板構造函數的參數推導出模板參數。例如,標準庫中有一個名為 std::pair 的類模板,在 <utility> 中定義,并在第1章中介紹。pair 存儲兩個可能不同類型的值,通常需要指定為模板參數。例如:FPr28資訊網——每日最新資訊28at.com

pair<int, double> pair1 { 1, 2.3 };

為了避免編寫模板參數,可以使用一個名為 std::make_pair() 的輔助函數模板。編寫自己的函數模板的細節將在本章后面討論。函數模板一直支持基于傳遞給函數模板的參數自動推導模板參數。因此,make_pair() 能夠根據傳遞給它的值自動推導出模板類型參數。例如,編譯器為以下調用推導出 pair<int, double>:FPr28資訊網——每日最新資訊28at.com

auto pair2 { make_pair(1, 2.3) };

使用類模板參數推導(CTAD),不再需要這樣的輔助函數模板。編譯器現在會根據傳遞給構造函數的參數自動推導出模板類型參數。對于 pair 類模板,您可以簡單地編寫以下代碼:FPr28資訊網——每日最新資訊28at.com

pair pair3 { 1, 2.3 }; // pair3 的類型為 pair<int, double>

當然,這僅在類模板的所有模板參數要么具有默認值,要么用作構造函數中的參數,從而可以推導出來時才有效。請注意,CTAD 要求有一個初始化器才能工作。以下是非法的:FPr28資訊網——每日最新資訊28at.com

pair pair4;

許多標準庫類支持 CTAD,例如 vector、array 等。FPr28資訊網——每日最新資訊28at.com

注意:這種類型推導對 std::unique_ptr 和 shared_ptr 無效。您向它們的構造函數傳遞 T*,這意味著編譯器必須在推導 <T> 或 <T[]> 之間選擇,如果選錯了就會很危險。因此,請記住,對于 unique_ptr 和 shared_ptr,您需要繼續使用 make_unique() 和 make_shared()。FPr28資訊網——每日最新資訊28at.com

2.用戶定義的推導指南

您也可以編寫自己的用戶定義推導指南來幫助編譯器。這些指南允許您編寫模板參數如何被推導的規則。這是一個高級主題,所以不會詳細討論,但會給出一個示例來展示它們的強大功能。假設您有以下 SpreadsheetCell 類模板:FPr28資訊網——每日最新資訊28at.com

template <typename T>class SpreadsheetCell {public:    SpreadsheetCell(T t) : m_content { move(t) } { }    const T& getContent() const { return m_content; }private:    T m_content;};

使用自動模板參數推導,您可以創建一個 std::string 類型的 SpreadsheetCell:FPr28資訊網——每日最新資訊28at.com

string myString { "Hello World!" };SpreadsheetCell cell { myString };

然而,如果您將 const char 傳遞給 SpreadsheetCell 構造函數,則類型 T 被推導為 const char,這不是您想要的!您可以創建以下用戶定義的推導指南,當向構造函數傳遞 const char* 作為參數時,使其將 T 推導為 std::string:FPr28資訊網——每日最新資訊28at.com

SpreadsheetCell(const char*) -> SpreadsheetCell<std::string>;

這個指南必須在類定義之外但在與 SpreadsheetCell 類相同的命名空間內定義。通用語法如下。explicit 關鍵字是可選的,其行為與構造函數的 explicit 相同。通常,這樣的推導指南也是模板。FPr28資訊網——每日最新資訊28at.com

explicit TemplateName(Parameters) -> DeducedTemplate;

本文鏈接:http://www.www897cc.com/showinfo-26-45494-0.html掌握C++模板的藝術:類型參數、默認值和自動推導

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 理解Java虛擬機(JVM):優化代碼執行效率的內部機制

下一篇: Python 也能干大事,訂閱與發布

標簽:
  • 熱門焦點
  • K60 Pro官方停產 第三方瞬間漲價

    雖然沒有官方宣布,但Redmi的一些高管也已經透露了,Redmi K60 Pro已經停產且不會補貨,這一切都是為了即將到來的K60 Ultra鋪路,屬于廠家的正常操作。但有意思的是該機在停產之后
  • Automa-通過連接塊來自動化你的瀏覽器

    1、前言通過瀏覽器插件可實現自動化腳本的錄制與編寫,具有代表性的工具就是:Selenium IDE、Katalon Recorder,對于簡單的業務來說可快速實現自動化的上手工作。Selenium IDEKat
  • .NET 程序的 GDI 句柄泄露的再反思

    一、背景1. 講故事上個月我寫過一篇 如何洞察 C# 程序的 GDI 句柄泄露 文章,當時用的是 GDIView + WinDbg 把問題搞定,前者用來定位泄露資源,后者用來定位泄露代碼,后面有朋友反
  • 當家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己&ldquo;當家&rdquo;的盒馬,開始加速謀生了。據盒馬官微消息,盒馬計劃今年開放生鮮供應鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經與
  • 機構稱Q2國內智能手機銷量同比下滑4% vivo份額重回第1

    7月29日消息,根據市場調查機構Counterpoint Research公布的最新報告,2023年第2季度中國智能手機銷量同比下降4%,創新自2014年以來第2季度銷量新低。報
  • 三星折疊屏手機去年銷售近1000萬臺 今年目標定為1500萬

    7月29日消息,三星率先發力可折疊手機市場,在全球市場已經取得了非常亮眼的成績,接下來會進一步鞏固和擴大這一優勢。三星在推出Galaxy Z Flip5和Galax
  • iQOO Neo8 Pro搶先上架:首發天璣9200+ 安卓性能之王

    經過了一段時間的密集爆料,昨日iQOO官方如期對外宣布:將于5月23日推出全新的iQOO Neo8系列新品,官方稱這是一款擁有旗艦級性能調校的作品。隨著發布時
  • SN570 NVMe SSD固態硬盤 價格與性能兼具

    SN570 NVMe SSD固態硬盤是西部數據發布的最新一代WD Blue系列的固態硬盤,不僅閃存技術更為精進,性能也得到了進一步的躍升。WD Blue SN570 NVMe SSD的包裝外
  • 中關村論壇11月25日開幕,15位諾獎級大咖將發表演講

    11月18日,記者從2022中關村論壇新聞發布會上獲悉,中關村論壇將于11月25至30日在京舉行。本屆中關村論壇由科學技術部、國家發展改革委、工業和信息化部、國務
Top 主站蜘蛛池模板: 华容县| 南丰县| 唐山市| 介休市| 宁海县| 尖扎县| 商丘市| 嘉禾县| 洛阳市| 河东区| 同心县| 紫金县| 巧家县| 罗田县| 枝江市| 怀仁县| 精河县| 赤水市| 元阳县| 贺兰县| 甘肃省| 梁河县| 固阳县| 东安县| 永年县| 兴安盟| 江永县| 延吉市| 西吉县| 洪雅县| 阳山县| 彭阳县| 云霄县| 新泰市| 辛集市| 贺州市| 高州市| 余干县| 阿瓦提县| 郑州市| 静乐县|