目录
模板
- 使用模板我们就可以写一个函数,而它的参数可以接收多种类型。比如:
// 普通函数, 只能接受 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;
}
buying from online mexican pharmacy: mexican online pharmacies prescription drugs – buying from online mexican pharmacy
Hi! I could have sworn I’ve visited this web site before but after looking at many of the articles I realized it’s new to me. Anyways, I’m certainly happy I came across it and I’ll be book-marking it and checking back regularly!
https://mexstarpharma.online/# mexican border pharmacies shipping to usa
Techno rozen Good post! We will be linking to this particularly great post on our site. Keep up the great writing
https://easyrxindia.com/# top 10 pharmacies in india
https://easyrxcanada.online/# canadianpharmacymeds
world pharmacy india world pharmacy india indian pharmacy
Your writing is not only informative but also incredibly inspiring. You have a knack for sparking curiosity and encouraging critical thinking. Thank you for being such a positive influence!
Hello! I could have sworn I’ve visited this site before but after browsing through a few of the articles I realized it’s new to me. Nonetheless, I’m certainly pleased I discovered it and I’ll be bookmarking it and checking back often.
buying from online mexican pharmacy buying from online mexican pharmacy mexican drugstore online
https://mexstarpharma.com/# mexico pharmacies prescription drugs
https://easyrxcanada.online/# ed meds online canada
indian pharmacy india online pharmacy top 10 pharmacies in india
http://easyrxcanada.com/# my canadian pharmacy rx
http://mexstarpharma.com/# mexican border pharmacies shipping to usa
https://mexstarpharma.com/# п»їbest mexican online pharmacies
https://easyrxindia.com/# cheapest online pharmacy india
Hey there! I just want to offer you a big thumbs up for your great info you have got right here on this post. I’ll be returning to your site for more soon.
Real Estate This is my first time pay a quick visit at here and i am really happy to read everthing at one place
I like it when individuals come together and share opinions. Great site, stick with it.
I was able to find good info from your blog posts.
Hello There. I found your weblog the usage of msn. This is an extremely neatly written article. I will be sure to bookmark it and return to learn extra of your helpful info. Thanks for the post. I will certainly comeback.
After going over a few of the blog articles on your web site, I honestly appreciate your technique of blogging. I saved it to my bookmark website list and will be checking back soon. Please check out my website as well and tell me what you think.
Good post. I learn something new and challenging on websites I stumbleupon on a daily basis. It will always be useful to read through articles from other authors and use something from other websites.
I¦ve been exploring for a little for any high quality articles or blog posts on this sort of house . Exploring in Yahoo I at last stumbled upon this site. Studying this information So i am happy to exhibit that I have an incredibly just right uncanny feeling I came upon just what I needed. I such a lot definitely will make sure to don¦t fail to remember this site and provides it a glance regularly.
Very good information. Lucky me I discovered your site by chance (stumbleupon). I’ve saved as a favorite for later!
Ive read several just right stuff here Certainly price bookmarking for revisiting I wonder how a lot effort you place to create this kind of great informative website
сервис по ремонту смартфонов
Hello! I just wish to offer you a huge thumbs up for your great info you have here on this post. I will be returning to your blog for more soon.
Great job on explaining this complex topic!프라그마틱
cytotec abortion pill https://tamoxifen.bid/# tamoxifen menopause
buy lasix online
Cytotec 200mcg price http://lipitor.guru/# lipitor 20 mg pill
lasix 100 mg tablet
I blog frequently and I genuinely appreciate your information. This article has really peaked my interest. I’m going to bookmark your website and keep checking for new information about once a week. I opted in for your RSS feed as well.
lowest price lipitor: Lipitor 10 mg price – lipitor 80 mg cost
lipitor 40 mg cost: Lipitor 10 mg price – buy lipitor 40 mg
I’m truly enjoying the design and layout of your website. It’s a very easy on the eyes which makes it much more enjoyable for me to come here and visit more often. Did you hire out a designer to create your theme? Fantastic work!
I blog quite often and I truly thank you for your information. The article has truly peaked my interest. I am going to bookmark your blog and keep checking for new information about once a week. I opted in for your Feed too.
buy cytotec over the counter https://lipitor.guru/# lipitor brand
generic lasix
buy cytotec pills: Misoprostol price in pharmacy – order cytotec online
Good info. Lucky me I recently found your blog by accident (stumbleupon). I’ve book-marked it for later.
Pretty! This has been an extremely wonderful article. Thanks for providing this info.
tamoxifen joint pain: Purchase Nolvadex Online – tamoxifen breast cancer prevention
п»їcytotec pills online: buy cytotec online – purchase cytotec
cytotec abortion pill https://lisinopril.guru/# lisinopril 10 12.55mg
lasix generic
buy cheap lipitor: buy lipitor 20mg – lipitor otc
сервисный ремонт apple
сервисный центр по ремонту apple
buy cytotec https://lisinopril.guru/# buy cheap lisinopril 40mg
lasix online
Ny weekly This is really interesting, You’re a very skilled blogger. I’ve joined your feed and look forward to seeking more of your magnificent post. Also, I’ve shared your site in my social networks!
Obrigado, estou procurando informações sobre esse tópico há algum tempo e a sua é a melhor que descobri até agora. Mas e em relação aos resultados financeiros? Você tem certeza sobre o fornecimento