目录
模板
- 使用模板我们就可以写一个函数,而它的参数可以接收多种类型。比如:
// 普通函数, 只能接受 int 类型参数,如果传入其他类型需要类型转换
int sum(int a, int b) {
return (a + b);
}
double sum(double a, double b) {
return (a + b);
}
- 由于不管是 int 参数、double参数,我们的 sum 函数求和内部代码都是一样的 (a + b),那么写多遍就变得麻烦,因此我们可以用模板的代替,只写一次代码,然后编译器会帮我们生成多个版本出来:
// 模板
template<typename T>
T sum(T a, T b) {
return (a + b);
}
// 编译会生成:
int sum(int a, int b) {
return (a + b);
}
double sum(double a, double b) {
return (a + b);
}
- c++的模板是编译期就会展开的,编译期会根据你使用到的类型,生成 template <int> ... 版本、template<double> ... 版本,而原本写的 template<T> ... 其实就是一个配置一样,运行时是不存在的,只是为了告诉编译期应该怎么生成代码。
可变参数模板
- 上面的求和只能2个数求和,那我如果有3个、4个、5个 ... 呢,难道要都写一遍吗:
int sum(int a, int b, int c) {
return (a + b + c);
}
int sum(int a, int b, int c, int d) {
return (a + b + c + d);
}
// ......
- 这时就可以请出可变参数模板来了,我们可以用三个点 来表示参数个数是不确定的:
template<typename T>
T sum(T... args) {
// 展开求和
}
- 但展开这个参数包 args 并不是当成数组遍历的,而是需要通过递归来实现:
template<typename T>
T mysum(T item) {
return item;
}
template<typename T>
T mysum(T item, T... args) {
return mysum(item) + mysum(args);
}
/// 入口
template<typename T>
T sum(T... args) {
return mysum(args);
}
- 最后一个函数 T sum(T... args) 才是我们暴露给用户使用的函数,而它其实是把参数包 args 转给了mysum(T item, T... args),可见原本在 sum 的参数包被拆出第一个参数 item,和剩下的其他参数 args 调用 mysum,假如 args 不存在,则是直接调用了 mysum(T item)
- 而 mysum(T item, T... args) 干嘛了呢, 它将 item 传给 mysum(T item) 处理,并将剩下的传给了"自己"!是的,此时其实就是递归,但请注意,以往我们递归调用的是函数本身,但这次递归不一样,举个例子来看看:
- 假如我们现在要调用 sum 了:sum(1, 2, 3, 4, 5),编译器就会生成接受5个参数的sum:
int sum(int arg0, int arg1, int arg2, int arg3, int arg4);
- 然后sum里面又调用了mysum,编译器接着按照mysum的声明,拆分sum传过来的5个参数为1 + 4生成:
int mysum(int item, int arg1, int arg2, int arg3, int arg4);
- 那接下来就看这个参数列表是 1+4 的mysum里面了,编译器先生成 mysum(T) 对应的 mysum(int):
int mysum(int item);
- 然后1+4的mysum里还把剩下的4个参数递归传给了自己这个模板,那就得把 4 再拆分成 1 + 3 生成mysum
int mysum(int item, int arg2, int arg3, int arg4);
- 到这里你可能已经理解它是怎么拆参数包的了,虽然叫递归,但其实每一次拆包调用的并不是函数本身,而是源于同一个模板生成的少一个参数的函数。
- 再往下就是接着生成:
int mysum(int item, int arg3, int arg4);
int mysum(int item, int arg4);
- 最终参数包 args 只有一个参数时就不用再生成了,它会直接去调用之前生成的 mysum(T item)
不定类型数量
- 前面的可变参数模板还不够彻底,它生成的函数接受的类型只有一个 T,那我能不能每一个参数类型都不一样呢?那么就需要对 template 那一行动手脚了:
template<typename T1, typename T2, typename ...Args>
T1 mysum(T2 item, Args... args);
- 可以看到,template内,我们单独声明了 返回值类型是 T1,第一个参数类型是 T2,而后面的参数类型则不确定,因此用 typename...Args 声明,在 mysum 的参数列表中 (T2 item, Args... args),Args...就表示args的数量是不确定的,由于Args本身类型数量也不确定,因此整体就表示 这里可以接受多个相同或不同类型的参数。
实现printf
- 有了上面的知识,实现printf就简单了,我们可以让它接收 第一个是字符串类型,然后加上多个任意类型的参数,并递归解析输出即可:
template<typename T>
int printNum(const std::string& str, int index, T&& item) {
auto doShift = true;
while (index < str.size()) {
if (index == (str.size() - 1) || str[index] != '%') {
cout << str[index];
++index;
}
else if(doShift) {
doShift = false;
++index;
switch (str[index]) {
case 's':
case 'd':
cout << item;
break;
}
++index;
}
else {
return index - 1;
}
}
return index - 1;
}
template<typename T, typename... Args>
int printNum(const std::string& str, int index, T&& item, Args&&... args) {
index = printNum(str, index, item);
return printNum(str, index + 1, std::forward<Args>(args)...);
}
template<typename ...Args>
void myPrintNum(const std::string& str, Args&&... args) {
int index = 0;
while (index < str.size()) {
if (str[index] != '%') {
cout << str[index];
++index;
}
else {
break;
}
}
index = printNum(str, index, std::forward<Args>(args)...);
++index;
while (index < str.size()) {
cout << str[index];
++index;
}
}
int main() {
// 调用,参数数量允许和字符串内数量不同,不会出错
myPrintNum("output: %d, %d, %d, %d ---", 123, 100.123, true);
return 0;
}
What i do not realize is in fact how you are no longer actually much more wellfavored than you might be right now Youre very intelligent You recognize thus considerably in relation to this topic made me in my view believe it from numerous numerous angles Its like men and women are not fascinated until it is one thing to do with Lady gaga Your own stuffs excellent All the time handle it up
buy cytotec online fast delivery: cytotec abortion pill – buy cytotec online
cytotec pills buy online: Cytotec 200mcg price – buy cytotec online fast delivery
nolvadex 10mg: tamoxifen benefits – tamoxifen premenopausal
buy prednisone 5mg canada: prednisone 10mg – prednisone 20mg online without prescription
The American streaming service announced today that it secured exclusive broadcast rights for the Premier League in Canada. Beginning next season on a three-year deal, it will replace DAZN as the country’s broadcaster for England’s top soccer league. DAZN, the revolutionary live and on-demand sport service, announced that it will be expanding into its fifth territory – Canada. DAZN is one of the most popular streaming services in Canada for sports fans. It’s a great place for watching live sports action like NFL games and Champions League football. However, it’s not the only Canadian sports service out there. In this guide, we’ll be looking at some of the top DAZN alternatives for Canadian sports fans to choose.
http://w.ballpennara.com/bbs/board.php?bo_table=free&wr_id=24944
Manchester United finished second in their group, losing out on the top spot to Spanish side Real Sociedad by goal difference. They will face Barcelona, who finished third to Bayern Munich and Inter Milan in their Champions League group. This match between former Champions League winners will be the headline clash of the UEFA Europa League playoffs 2022-23. They face a Frankfurt side that eased their way past West Ham United in the semi-finals, and are now looking to lift the trophy for the second time in their history. Not a member? Join today \n Al momento abbiamo problemi con il servizio. Mentre lavoriamo per risolverli\n puoi continuare a guardare gli eventi live selezionando l’opzione di\n seguito.\n Although both semi-final matches will air on the BBC TV channel, the first semi-final match between Manchester City and Sheffield United will only be available for streaming on the ITVX platform. The second semi-final match between Brighton & Hove Albion and Manchester United will stream on BBC iPlayer. Both matches will stream on ESPN+ and Hulu.
buy cytotec pills online cheap: buy cytotec over the counter – buy cytotec online
buy cytotec pills: cytotec buy online usa – buy cytotec over the counter
Somebody essentially lend a hand to make significantly posts I might state That is the very first time I frequented your web page and up to now I surprised with the research you made to create this particular put up amazing Excellent job
What i dont understood is in reality how youre now not really a lot more smartlyfavored than you might be now Youre very intelligent You understand therefore significantly in terms of this topic produced me personally believe it from a lot of numerous angles Its like women and men are not interested except it is one thing to accomplish with Woman gaga Your own stuffs outstanding Always care for it up
prednisone brand name prednisone 40 mg tablet prednisone 5 tablets
http://zithromaxbestprice.pro/# buy zithromax online fast shipping
buy cytotec online: buy cytotec pills online cheap – Misoprostol 200 mg buy online
zithromax drug: how to get zithromax – where to buy zithromax in canada
cost generic propecia without a prescription: buying cheap propecia price – get cheap propecia
buy propecia now get propecia price cost of propecia without insurance
tamoxifen and grapefruit clomid nolvadex nolvadex d
Pretty! This was an incredibly wonderful post. Thanks for providing these details.
buying generic propecia propecia order cost of generic propecia without dr prescription
https://prednisonebestprice.pro/# prednisone 20 mg tablet price
https://prednisonebestprice.pro/# apo prednisone
zithromax 500 without prescription: zithromax for sale online – zithromax capsules 250mg
https://cytotecbestprice.pro/# buy cytotec pills online cheap
generic zithromax 500mg how to get zithromax over the counter how much is zithromax 250 mg
http://prednisonebestprice.pro/# prednisone without prescription.net
prednisone 20 mg tablet: prednisone 10mg tablet cost – prednisone pill prices
http://propeciabestprice.pro/# buying propecia for sale
where can you buy prednisone: where to buy prednisone uk – prednisone online paypal
https://zithromaxbestprice.pro/# zithromax capsules
purchase prednisone from india prednisone nz cost of prednisone 5mg tablets
Public policy responses addressing causes and effects of income inequality in the US include: progressive tax incidence adjustments, strengthening social safety net provisions such as Aid to Families with Dependent Children, welfare, the food stamp program, Social Security, Medicare, and Medicaid, organizing community interest groups, increasing and reforming higher education subsidies, increasing infrastructure spending, and placing limits on and taxing rent-seeking.
how does tamoxifen work: tamoxifen menopause – tamoxifen warning
common side effects of tamoxifen tamoxifen lawsuit tamoxifen medication
https://zithromaxbestprice.pro/# buy zithromax 1000mg online
cost of tamoxifen tamoxifen adverse effects tamoxifen side effects forum
http://propeciabestprice.pro/# get propecia tablets
15 mg prednisone daily: 6 prednisone – prednisone 10mg cost
http://nolvadexbestprice.pro/# tamoxifen dosage
casino
tamoxifen hot flashes tamoxifen citrate pct tamoxifen breast cancer
http://nolvadexbestprice.pro/# tamoxifen hot flashes
http://propeciabestprice.pro/# get cheap propecia without a prescription
http://prednisonebestprice.pro/# where to buy prednisone uk
liquid tamoxifen: tamoxifen and antidepressants – effexor and tamoxifen
http://cytotecbestprice.pro/# cytotec buy online usa
order cheap propecia without dr prescription: cost cheap propecia without a prescription – buying cheap propecia without dr prescription
order cheap propecia price cost cheap propecia pill cost of cheap propecia pill
buy cytotec over the counter purchase cytotec order cytotec online
https://propeciabestprice.pro/# buy cheap propecia pill
generic zithromax online paypal: can you buy zithromax over the counter in canada – can i buy zithromax over the counter in canada