国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

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

開發 前端
在 Grid 示例中,Grid 模板有一個模板參數:存儲在網格中的類型。編寫類模板時,您需要在尖括號內指定參數列表。

一、模板參數

1.類型模板參數

在 Grid 示例中,Grid 模板有一個模板參數:存儲在網格中的類型。編寫類模板時,您需要在尖括號內指定參數列表,例如:

template <typename T>

這個參數列表類似于函數或方法中的參數列表。與函數和方法一樣,你可以編寫具有任意多個模板參數的類。此外,這些參數不必是類型,它們可以有默認值。

2.非類型模板參數

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

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

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];
};

注意,模板參數列表需要三個參數:存儲在網格中的對象類型,以及網格的寬度和高度。寬度和高度用于創建存儲對象的二維數組。下面是類方法的定義:

// 類方法定義
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> 來指定三個模板參數。你可以這樣實例化并使用這個模板:

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);

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

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

然而,如果你將高度定義為常量,則可以編譯:

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

具有正確返回類型的 constexpr 函數也可以工作。例如,如果你有一個返回 size_t 的 constexpr 函數,你可以用它來初始化高度模板參數:

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

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

注意:非類型模板參數成為實例化對象類型規范的一部分。

二、類模板參數的默認值

設置高度和寬度的默認值

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

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

在方法定義的模板規范中,您不需要為 T、WIDTH 和 HEIGHT 指定默認值。例如,這是 at() 方法的實現:

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,只需指定元素類型,元素類型和寬度,或元素類型、寬度和高度:

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

請注意,如果您不指定任何類模板參數,您仍然需要指定一組空的尖括號。例如,以下代碼無法編譯!

Grid myIntGrid;

類模板參數列表中默認參數的規則與函數或方法相同;也就是說,您可以從右邊開始為參數提供默認值。

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

1.自動推導模板參數

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

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

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

auto pair2 { make_pair(1, 2.3) };

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

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

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

pair pair4;

許多標準庫類支持 CTAD,例如 vector、array 等。

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

2.用戶定義的推導指南

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

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:

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

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

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

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

explicit TemplateName(Parameters) -> DeducedTemplate;
責任編輯:趙寧寧 來源: coding日記
相關推薦

2024-01-17 23:10:59

C++函數模板開發

2023-09-25 12:12:01

C++自動返回

2024-02-19 08:11:40

C++編程尾返回類型推導

2010-02-03 17:42:33

C++模板參數

2024-12-19 11:30:00

C++17CTAD代碼

2010-02-04 14:01:43

C++非類型類模板參數

2010-02-04 14:22:25

C++函數模板非類型參

2010-09-28 10:23:36

SQL修改字段

2022-11-14 07:08:23

Python函數參數

2023-09-01 21:20:06

授權委派KPI

2024-04-29 07:48:04

C++FinalOverride

2010-01-08 16:52:57

C++和C#

2012-08-01 09:50:11

交互設計UI設計

2009-08-31 14:34:46

C#值類型C#結構類型

2010-01-28 13:45:06

C++數組

2009-09-11 12:31:15

C# WinForm控設置默認值

2016-12-20 16:35:52

NodeJSC++類型轉換

2024-01-29 01:30:00

函數C++編程

2016-12-07 11:23:52

NodeJSC++

2011-04-11 10:09:20

委托反饋C++
點贊
收藏

51CTO技術棧公眾號

亚洲色图激情小说| 4kfree性满足欧美hd18| 国产麻豆精品一区二区| 九九热在线免费| 欧美日韩国产小视频| 久久九九精品视频| 欧美日韩免费高清| 亚洲欧美日韩中文播放| 成人爽a毛片免费啪啪动漫| 欧美最顶级的aⅴ艳星| 精品一区二区三区视频在线观看| 黄色网免费看| 亚洲欧美国产va在线影院| 欧美一区不卡| 成人免费网站视频www| 国产午夜精品理论片a级探花| 91偷拍一区二区三区精品| 5月婷婷6月丁香| 精品国精品国产尤物美女| 日韩久久久久| 色免费在线视频| 亚洲天堂av在线播放| 免费在线观看成人av| 深夜福利视频一区| 91a在线视频| 99精品视频免费在线观看| 69成人在线| 91日韩久久| 综合分类小说区另类春色亚洲小说欧美| 国产一线二线在线观看| 91亚色免费| 一区二区三区在线免费视频 | 三上悠亚在线观看| 免费av在线一区| 国产一区999| 成人免费网址| 91免费看蜜桃| 亚洲高清免费观看高清完整版在线观看| 欧美黄页免费| 激情视频小说图片| 精品三级在线观看| 国产日韩精品视频一区二区三区 | 亚洲人成欧美中文字幕| 最新亚洲视频| 日韩美女一级视频| 国产精品免费电影| 樱桃视频在线观看一区| 欧美视频二区欧美影视| 国产又粗又猛又爽又黄的网站| 精品久久国产老人久久综合| 国产欧美69| аⅴ资源新版在线天堂| 亚洲综合大片69999| 精品国产成人av| 日韩在线观看| 国产三级av在线| 日本亚洲欧美成人| 国产欧美一区二区在线观看| 国产乱码精品一区二区三区亚洲人| 成人黄色大片网站| 在线性视频日韩欧美| 成人永久aaa| 久久av影院| 91视频免费版污| 欧美亚州一区二区三区| 悠悠色在线精品| 久久麻豆精品| 久青青在线观看视频国产| 国产精品视频免费一区二区三区| 欧美日韩专区在线| 99国产精品视频免费观看一公开| 1区2区3区在线观看| 国产精品久久久久久久小唯西川| 欧美午夜精品久久久| 久久国产精品第一页| 久热国产在线| 中文字幕精品久久| 亚洲无人区一区| av在线电影院| 国产精品日本一区二区| 色哟哟欧美精品| 国产精品亚洲综合久久| 少女频道在线观看免费播放电视剧| 亚洲美女搞黄| 在线午夜精品自拍| 国产精品网站在线| 色135综合网| 在线视频自拍| 欧美精品九九久久| 日韩欧美亚洲另类制服综合在线| 久久91麻豆精品一区| 日本高清好狼色视频| 色综合久久精品亚洲国产| 国内不卡的二区三区中文字幕| 欧美极品免费| 日本在线视频中文有码| 日本一区高清不卡| 亚洲天堂av高清| 中文字幕高清一区| 天天综合亚洲| 欧美寡妇性猛交xxx免费| 男的插女的下面视频| 91黑丝在线观看| 色偷偷成人一区二区三区91| 蜜桃在线一区二区三区| 亚洲免费资源| 性欧美18+| 水蜜桃一区二区| 欧美激情高清视频| 在线观看网站黄不卡| 国产成人精品aa毛片| 精品久久电影| 久草免费在线视频| 成年人福利视频| 精品蜜桃传媒| 久久亚洲精品一区二区| 欧美性猛交xxxx| 丁香桃色午夜亚洲一区二区三区| 免费一区二区三区视频导航| 黄色成年人视频在线观看| 日韩一级在线免费观看| dy888夜精品国产专区| 日韩在线视频导航| 黄色一区二区在线观看| 国产麻豆成人精品| 日韩激情一区| 欧美三区四区| 欧美日韩在线精品一区二区三区激情综 | 国产a级片网站| 91精品视频大全| 久久久久久av| 日韩一中文字幕| 中文字幕精品在线| 国产suv精品一区二区| 国产欧美一区二区精品性色 | 国产精品88a∨| 精品伦理精品一区| 亚洲美女偷拍久久| 精品在线免费视频| 婷婷综合久久| 视频一区国产| 狂野欧美性猛交xxxxx视频| 一本大道香蕉久久| 国产爆乳无码一区二区麻豆| 国产精品视频久久久| 国产亚洲一区二区精品| 91激情在线视频| 亚洲欧美在线视频观看| 国产v综合v亚洲欧| 鲁大师成人一区二区三区 | 日韩欧美午夜| 91成人小视频| 欧美大片黄色| 九九热视频在线观看| 成人禁在线观看网站| 久久久久久久久久伊人| 久久久久久久久久久久久久久久av | 91精品国产综合久久久久| 国产精品国产三级国产普通话三级| 经典三级在线一区| 一本一本久久| 97色伦图片97综合影院| 97精品久久| 国产95亚洲| 日本成人片在线| heyzo高清国产精品| 午夜视频在线| 国产毛片av在线| 亚洲私人影吧| 国外男同性恋在线看| 五月天电影免费在线观看一区| 男女av免费观看| 国产成人无码a区在线观看视频| 中文字幕久精品免| 亚洲一二三区在线| 日韩一区不卡| 日本不卡一区二区三区在线观看 | 国产伦精品一区二区三区四区免费| 97在线观看视频国产| xxxx性欧美| 日韩一区二区欧美| 日韩禁在线播放| 日韩h在线观看| 日韩大陆欧美高清视频区| 日韩精品一区在线| 制服丝袜中文字幕亚洲| 精品1区2区3区| 欧美日韩视频专区在线播放| 欧美专区在线观看一区| 在线一区二区三区四区| 91久久一区二区| 欧亚洲嫩模精品一区三区| 在线免费观看日本欧美| 欧美专区日韩专区| 欧美亚州韩日在线看免费版国语版| 色综合久久天天| 欧美日韩高清一区二区| 欧美电视剧在线看免费| 亚洲第一福利网站| 亚洲人成在线一二|