C 17 之 利用建構函式推導模板引數型別

2021-08-18 16:54:00 字數 1975 閱讀 5872

在 c++17 之前,

通過向模板類的建構函式傳遞引數無法推導出類的模板引數型別.

一般要通過乙個幫助函式來構造乙個物件,

通過傳遞給幫助函式的引數推導出引數型別,

然後在幫助函式中返回乙個構造好的物件. 下面介紹 c++17 之前的做法與

c++17 的便利性.

template

class my_class , t2, t3

{}};

要構造 my_class 的物件, 可以通過下面的方法

my_class obj;
通過上面這種方法, 當使用時要指定一堆的模板引數, 使用不太方便,

因此可以定義乙個幫助函式, 比如 make_my_class

my_classmake_my_class(t1 t1, t2 t2, t3 t3)

;}

之後就可以通過下面的方法構造物件 my_obj, 可以得到模板類型別為

my_class.

auto my_obj (make_my_class(1, 2, 3.0));
在 c++17 中, 可以直接通過建構函式的引數型別來推導出模板引數型別.

因此可以象下面的方法構造物件 obj, 可以得到模板類型別為

my_class.

my_class

obj(1, 2, 3.0);

雖然 c++17 利用建構函式的引數型別來推導模板型別使用方便, 但有時候也無法推導,

考慮下面的類定義

// 模板類定義, 用於求和, 和儲存於成員變數 value 中

t>

struct sum {}

};// 如果傳遞給建構函式的引數型別都相同, 可以推導出 t 的型別即為引數型別

sum my_sum; // sum::value 為 6

// 如果傳遞給建構函式的引數型別不同, 則會編譯錯誤

// sum my_sum

當然, 傳遞給 sum 建構函式的還可能會是char*std::string.

為了使用其能正常工作, 需要尋找出眾多引數型別中的最普通型別, 可以利用

std::common_type_t<...>. 在上面**的基礎上增加乙個更加泛化的版本

// (1)

t>

struct sum {}

};// (2)

template ... ts>

sum(ts&& ... ts) -> sum>;

此時, 如果傳遞給建構函式的引數型別相同, 直接會呼叫 (1) 的版本.

如果傳遞給建構函式的引數不同, 會呼叫 (2) 版本. 比如

// 得到 int, int, double 三種型別的普通型別為 double

// 最終會推導出乙個 sum的結構型別

sum int_sum;

// 得到 std::string, const char* 更普通的型別為 std::string

// 最終會推導出乙個 sum的結構型別

// sum ::value 為 std:string("abcdef")

sum string_sum , "def"};

從 c++17 開始, 可以很方便的構造乙個模板類物件, 從而活動乙個幫助函式. 在 c++

標準庫中, 很多make_***(...)的幫助函式, 如 std::make_pair(),

std::make_tuple(), 在 c++17 之後, 這些幫助函式都會成為 deprecated 狀態,

只是為前向相容而保留.

c 17中的any模板類

此外在c 17之前,各大類庫基本都提供了自己variant萬能類,c 17 標準庫引入any類可取代之,並提供更好的型別安全和效率。any 類可以容納任意型別 可構造,複製 的值。用途目的之一可避免小物件的動態記憶體分配。例如在乙個陣列中存放基類及子類,實現基類多型訪問。std vectorobjs...

c 類模板物件做函式引數

類模板物件做函式引數 學習目標 一共有三種傳入方式 指定傳入的型別 直接顯示物件的資料型別 引數模板化 將物件中的引數變為模板進行傳遞 整個類模板化 將這個物件型別 模板化進行傳遞 示例 include 類模板 template class person void showperson public...

c 呼叫基類的建構函式(模板類)

如下 include include include using namespace std template class base template base base t n template void base tostring template derive derive t n base ...