在 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 ...