成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C++函數(shù)模板詳解,輕松實(shí)現(xiàn)通用函數(shù)

開(kāi)發(fā) 前端
理論上,C++ 語(yǔ)言允許您編寫(xiě)函數(shù)模板特化,就像您可以編寫(xiě)類(lèi)模板特化一樣。但這樣的函數(shù)模板特化不參與重載解析,因此可能表現(xiàn)出意外的行為。相反,您可以用非模板函數(shù)重載函數(shù)模板。

一、函數(shù)模板

1.編寫(xiě)通用函數(shù)

您也可以為獨(dú)立的函數(shù)編寫(xiě)模板。其語(yǔ)法與類(lèi)模板類(lèi)似。例如,您可以編寫(xiě)以下通用函數(shù)來(lái)在數(shù)組中查找一個(gè)值并返回其索引:

static const size_t NOT_FOUND { static_cast<size_t>(-1) };

template <typename T>
size_t Find(const T& value, const T* arr, size_t size) {
    for (size_t i { 0 }; i < size; i++) {
        if (arr[i] == value) {
            return i; // 找到了; 返回索引。
        }
    }
    return NOT_FOUND; // 沒(méi)找到; 返回 NOT_FOUND。
}

注意:當(dāng)然,當(dāng)元素未找到時(shí),您可以不返回某種哨兵值(如 NOT_FOUND),而是改寫(xiě)此代碼以返回 std::optional<size_t> 而不是 size_t。這將是使用 optional 的有趣練習(xí)。

2.Find() 函數(shù)模板的應(yīng)用

Find() 函數(shù)模板可以在任何類(lèi)型的數(shù)組上工作。例如,您可以用它來(lái)在 int 數(shù)組中查找 int 的索引,或者在 SpreadsheetCell 數(shù)組中查找 SpreadsheetCell。您可以通過(guò)兩種方式調(diào)用該函數(shù):顯式地用尖括號(hào)指定類(lèi)型參數(shù),或者省略類(lèi)型并讓編譯器從參數(shù)中推斷出類(lèi)型參數(shù)。以下是一些示例:

int myInt { 3 }, intArray[] {1, 2, 3, 4};
const size_t sizeIntArray { size(intArray) };
size_t res;

// 通過(guò)推斷調(diào)用 Find<int>。
res = Find(myInt, intArray, sizeIntArray);

// 顯式地調(diào)用 Find<int>。
res = Find<int>(myInt, intArray, sizeIntArray);

// 其他示例
double myDouble { 5.6 }, doubleArray[] {1.2, 3.4, 5.7, 7.5};
const size_t sizeDoubleArray { size(doubleArray) };

// 通過(guò)推斷調(diào)用 Find<double>。
res = Find(myDouble, doubleArray, sizeDoubleArray);

// 顯式地調(diào)用 Find<double>。
res = Find<double>(myDouble, doubleArray, sizeDoubleArray);

SpreadsheetCell cell1 { 10 }
SpreadsheetCell cellArray[] { SpreadsheetCell { 4 }, SpreadsheetCell { 10 } };
const size_t sizeCellArray { size(cellArray) };
res = Find(cell1, cellArray, sizeCellArray);
res = Find<SpreadsheetCell>(cell1, cellArray, sizeCellArray);

3.數(shù)組大小的自動(dòng)推斷

之前的 Find() 函數(shù)實(shí)現(xiàn)需要作為參數(shù)之一的數(shù)組大小。有時(shí)編譯器知道數(shù)組的確切大小,例如,對(duì)于基于堆棧的數(shù)組。能夠在不需要傳遞數(shù)組大小的情況下調(diào)用 Find() 會(huì)很方便。這可以通過(guò)添加以下函數(shù)模板來(lái)實(shí)現(xiàn)。實(shí)現(xiàn)只是將調(diào)用轉(zhuǎn)發(fā)到之前的 Find() 函數(shù)模板。這也表明,函數(shù)模板可以像類(lèi)模板一樣接受非類(lèi)型參數(shù)。

template <typename T, size_t N>
size_t Find(const T& value, const T(&arr)[N]) {
    return Find(value, arr, N);
}

這個(gè)版本的 Find() 語(yǔ)法看起來(lái)有點(diǎn)奇怪,但其使用非常直接,如下例所示:

int myInt { 3 }, intArray[] {1, 2, 3, 4};
size_t res { Find(myInt, intArray) };

4.函數(shù)模板的定義和導(dǎo)出

與類(lèi)模板方法定義一樣,函數(shù)模板的定義(不僅僅是原型)必須對(duì)使用它們的所有源文件可用。因此,如果多個(gè)源文件使用它們,您應(yīng)該將定義放在模

塊接口文件中并導(dǎo)出它們。

最后,函數(shù)模板的模板參數(shù)可以像類(lèi)模板一樣有默認(rèn)值。

注意:C++ 標(biāo)準(zhǔn)庫(kù)提供了一個(gè)比這里展示的 Find() 函數(shù)模板更強(qiáng)大的 std::find() 函數(shù)模板。

二、函數(shù)模板重載

1.函數(shù)模板與特化

理論上,C++ 語(yǔ)言允許您編寫(xiě)函數(shù)模板特化,就像您可以編寫(xiě)類(lèi)模板特化一樣。然而,您很少需要這樣做,因?yàn)檫@樣的函數(shù)模板特化不參與重載解析,因此可能表現(xiàn)出意外的行為。相反,您可以用非模板函數(shù)重載函數(shù)模板。例如,您可能想為 const char* 類(lèi)型的 C 風(fēng)格字符串編寫(xiě)一個(gè) Find() 重載,這個(gè)重載使用 strcmp()來(lái)比較,而不是用 operator==,因?yàn)?nbsp;== 只會(huì)比較指針,而不是實(shí)際的字符串。以下是這樣的重載:

size_t Find(const char* value, const char** arr, size_t size) {
    for (size_t i { 0 }; i < size; i++) {
        if (strcmp(arr[i], value) == 0) {
            return i; // 找到了; 返回索引。
        }
    }
    return NOT_FOUND; // 沒(méi)找到; 返回 NOT_FOUND。
}

這個(gè)函數(shù)重載的使用方式如下:

const char* word { "two" };
const char* words[] { "one", "two", "three", "four" };
const size_t sizeWords { size(words) };
size_t res { Find(word, words, sizeWords) }; // 調(diào)用非模板函數(shù)。

如果您顯式指定模板類(lèi)型參數(shù),如下所示,那么將調(diào)用函數(shù)模板,其中 T=const char,而不是 const char

res = Find<const char*>(word, words, sizeWords);

2.重載與特化的選擇

在選擇重載函數(shù)模板時(shí),應(yīng)該考慮到函數(shù)模板特化可能不參與重載解析的規(guī)則。通常,重載函數(shù)模板與非模板函數(shù)是一種更安全且可預(yù)測(cè)的方法,特別是當(dāng)涉及到特定類(lèi)型的特定處理,如在處理 C 風(fēng)格字符串時(shí)使用 strcmp() 而不是默認(rèn)的等號(hào)運(yùn)算符。

三、類(lèi)模板的友元函數(shù)模板

1.重載運(yùn)算符的函數(shù)模板

當(dāng)您想在類(lèi)模板中重載運(yùn)算符時(shí),函數(shù)模板非常有用。例如,您可能想為 Grid 類(lèi)模板重載加法運(yùn)算符(operator+),以便將兩個(gè)網(wǎng)格相加。結(jié)果將是一個(gè)與兩個(gè)操作數(shù)中較小的 Grid 同等大小的 Grid。僅當(dāng)兩個(gè)單元格都包含實(shí)際值時(shí),才會(huì)相加對(duì)應(yīng)的單元格。假設(shè)您想讓您的 operator+ 成為一個(gè)獨(dú)立的函數(shù)模板。定義應(yīng)該放在 Grid.cppm 模塊接口文件中,如下所示。該實(shí)現(xiàn)使用 <algorithm> 中定義的 std::min() 來(lái)返回兩個(gè)給定參數(shù)的最小值:

export template <typename T>
Grid<T> operator+(const Grid<T>& lhs, const Grid<T>& rhs) {
    size_t minWidth { std::min(lhs.getWidth(), rhs.getWidth()) };
    size_t minHeight { std::min(lhs.getHeight(), rhs.getHeight()) };
    Grid<T> result { minWidth, minHeight };
    
    for (size_t y { 0 }; y < minHeight; ++y) {
        for (size_t x { 0 }; x < minWidth; ++x) {
            const auto& leftElement { lhs.m_cells[x][y] };
            const auto& rightElement { rhs.m_cells[x][y] };
            if (leftElement.has_value() && rightElement.has_value()) {
                result.at(x, y) = leftElement.value() + rightElement.value();
            }
        }
    }
    return result;
}

要查詢(xún)一個(gè) optional 是否包含實(shí)際值,您使用 has_value() 方法,而 value() 用于檢索這個(gè)值。這個(gè)函數(shù)模板適用于任何 Grid,只要網(wǎng)格中存儲(chǔ)的元素類(lèi)型有加法運(yùn)算符。這個(gè)實(shí)現(xiàn)的唯一問(wèn)題是它訪(fǎng)問(wèn)了 Grid 類(lèi)的私有成員 m_cells。一個(gè)顯而易見(jiàn)的解決方案是使用公共 at() 方法,但讓我們看看如何讓函數(shù)模板成為類(lèi)模板的友元。

2.使函數(shù)模板成為類(lèi)模板的友元

在此示例中,您可以使運(yùn)算符成為 Grid 類(lèi)的友元。然而,Grid 類(lèi)和 operator+ 都是模板。您真正想要的是,對(duì)于特定類(lèi)型 T 的每個(gè) operator+ 實(shí)例化,都是同一類(lèi)型的 Grid 模板實(shí)例化的友元。語(yǔ)法如下:

// 前向聲明 Grid 模板。
export template <typename T>
class Grid;

// templatized operator+ 的原型。
export template <typename T>
Grid<T> operator+(const Grid<T>& lhs, const Grid<T>& rhs);

export template <typename T>
class Grid {
public:
    friend Grid operator+<T>(const Grid& lhs, const Grid& rhs);
    // 省略其他內(nèi)容
};

這種友元聲明很微妙:您在說(shuō),對(duì)于類(lèi)型 T 的模板實(shí)例,operator+ 的 T 實(shí)例化是一個(gè)友元。換句話(huà)說(shuō),類(lèi)實(shí)例化和函數(shù)實(shí)例化之間存在一對(duì)一的友元映射。特別注意 operator+ 上的顯式模板規(guī)范 <T>。這個(gè)語(yǔ)法告訴編譯器 operator+ 本身是一個(gè)模板。

3.模板參數(shù)推斷

編譯器根據(jù)傳遞給函數(shù)模板的參數(shù)推斷函數(shù)模板參數(shù)的類(lèi)型。無(wú)法推斷的模板參數(shù)必須明確指定。例如,以下 add() 函數(shù)模板需要三個(gè)模板參數(shù):返回值的類(lèi)型和兩個(gè)操作數(shù)的類(lèi)型:

template <typename RetType, typename T1

, typename T2>
RetType add(const T1& t1, const T2& t2) {
    return t1 + t2;
}

您可以通過(guò)以下方式調(diào)用此函數(shù)模板,明確指定所有三個(gè)參數(shù):

auto result { add<long long, int, int>(1, 2) };

然而,因?yàn)槟0鍏?shù) T1 和 T2 是函數(shù)的參數(shù),編譯器可以推斷這兩個(gè)參數(shù),所以您可以只指定返回值類(lèi)型來(lái)調(diào)用 add():

auto result { add<long long>(1, 2) };

這只有在要推斷的參數(shù)位于參數(shù)列表的最后時(shí)才有效。假設(shè)函數(shù)模板如下定義:

template <typename T1, typename RetType, typename T2>
RetType add(const T1& t1, const T2& t2) {
    return t1 + t2;
}

您必須指定 RetType,因?yàn)榫幾g器無(wú)法推斷該類(lèi)型。然而,由于 RetType 是第二個(gè)參數(shù),您也必須顯式指定 T1:

auto result { add<int, long long>(1, 2) };

您還可以為返回類(lèi)型模板參數(shù)提供默認(rèn)值,以便在不指定任何類(lèi)型的情況下調(diào)用 add():

template <typename RetType = long long, typename T1, typename T2>
RetType add(const T1& t1, const T2& t2) {
    return t1 + t2;
}
...
auto result { add(1, 2) };
責(zé)任編輯:趙寧寧 來(lái)源: coding日記
相關(guān)推薦

2023-12-13 10:51:49

C++函數(shù)模板編程

2010-02-05 17:34:37

C++函數(shù)模板

2024-01-17 23:10:59

C++函數(shù)模板開(kāi)發(fā)

2010-02-04 14:22:25

C++函數(shù)模板非類(lèi)型參

2010-02-02 15:59:32

C++賦值函數(shù)

2010-02-02 18:01:47

C++字符串替換函數(shù)

2010-02-04 09:26:23

C++模板函數(shù)重載

2024-04-01 09:13:20

C++函數(shù)遞增

2010-02-03 15:52:55

C++ clock()

2011-08-22 17:25:31

LuaC++函數(shù)

2010-02-05 15:59:26

C++函數(shù)重載

2010-01-18 17:38:54

C++虛函數(shù)表

2011-08-22 17:13:00

LuaC++函數(shù)

2010-02-01 13:26:58

C++讀取CSV文件

2010-02-02 09:49:02

C++模板

2010-01-28 13:35:41

調(diào)用C++函數(shù)

2010-01-18 16:56:30

C++函數(shù)

2009-09-10 16:30:11

C#排序函數(shù)

2010-01-27 17:16:52

C++構(gòu)造函數(shù)

2010-01-26 10:42:26

C++函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 午夜精品久久久久久 | 亚洲视频免费在线 | 超碰97人人人人人蜜桃 | 国产一区二区欧美 | 亚洲国产成人精品女人久久久 | 无码国模国产在线观看 | 中文成人在线 | 欧美成人免费在线 | 日韩精品一区二区三区老鸭窝 | 99精品视频免费在线观看 | 欧美日韩一区不卡 | 国产日韩精品视频 | 欧美极品一区二区 | 91九色视频| 久久逼逼| 久久国产精品视频 | 日韩黄色av| 国产黄色精品 | 国产亚洲一区二区三区在线 | 性色av香蕉一区二区 | 天天射夜夜操 | 欧美中文在线 | 国产欧美在线 | 91麻豆精品国产91久久久资源速度 | 国产欧美精品区一区二区三区 | 一区观看 | 中文字幕av中文字幕 | 99re国产视频 | 99爱在线观看 | 亚洲精品在线播放 | 中文字幕观看 | 国产精品久久国产精品久久 | 久久三级影院 | 免费毛片网站 | 免费成人高清 | av播播 | 成人在线网 | 91精品国产91久久久久久最新 | 中文字幕不卡视频在线观看 | 欧美一区二区三区视频 | 亚洲男人的天堂网站 |