Comments (4)
我再阐述一下我的思路吧:
(1)为什么不存在递归呢?第16.4.1节不就是以print作为例子吗?一个递归版本,一个非递归版本。非递归版本用来终止递归.
(2)另外我的意思是,不需要那个非递归版本的print来终止递归,利用<if (!sizeof...(args)>
就可以判断终止条件.我测试了一下,print(1,2,3,4)时它并不总是3,而是随着函数的递归调用变成了2,1.然后在第三次调用(既参数包为空)时编译器选定了非递归版本的print.
(3)我的问题在于将非递归版本的print注释掉就报错.我的代码如下:
#include <iostream>
using std::cout;
using std::endl;
//template<typename T> //注释掉这个非递归版本的print
//void print(const T& t)
//{
// cout << t;
//}
template<typename T, typename... args>
void print(const T &t, const args&... rest)
{
auto m = sizeof...(args);//测试代码,m并不总是3.而是每次减1
if (!sizeof...(args))//参数包为空
{
cout << t << endl;//没有分隔符
return;
}
cout << t << ", ";
print(rest...);/*这里不就是递归调用么?
每一次调用就会将参数包的第一个参数绑定到 t 上面,而参数包的参数就少一个,3,2,1,
最后一次就应该是0了,但是存在非递归版本的print时编译器会选择非递归版本的函数,
如果没有非递归,那么递归版本也应该是可行函数啊?但是会报错*/
}
int main()
{
print(1,2,3,4);
}
不知道我有没有说明白我的困惑?
from cppprimer.
@pyb1993 不好意思, 是我完全理解错了。
我基本上了解你的意图了, 但恐怕这是无法实现的。这里的递归, 和通常意义上的 runtime 递归是有区别的。原代码中的双函数递归, 是在编译期就确定的静态递归。
你试图将双函数简化成单函数, 但用的条件 if (!sizeof...(args))
却是在编译期无法确定的,只有在 runtime 才可以确定其值(如你所言,每次减 1)。所以这一点和模版静态递归的本质冲突了, 故无法实现。
再说说你遇到的编译错误,编译时, 编译器碰到 print(rest...);
就会尝试去解开 rest 这个 pack. 而由于 if (!sizeof...(args))
在编译期间无法确定其值,所以对于编译器而言,这个条件形同虚设。于是,解到最后, 发现最终的参数个数, 是 1. 而它找来找去, 也没看到参数个数为 1 的 print
声明。于是它困惑了,并抱怨在 IDE 里。
我也尝试了一下实现你的意图, 单函数递归来解这道题,却很遗憾的没有找到解决方案。。非常抱歉。
from cppprimer.
首先谢谢您的解答,我基本理解了.但是有一点不同意见 :
#[0]:我认为编译器不是在解到参数为1的时候报错的,而是在参数为0的时候报错的.```
##[1]因为我调用print(1)进行测试,发现是可以的,因为参数包rest是可以为空的.编译器编译的时候忽略了递归的终止条件(以前我忽略了模板静态递归的特点!),所以当参数只有1个(rest为空)的情况下它还会去调用print(rest...),然而这个时候一个参数都没有提供给print函数,这显然是不可以的.
###[2]这是我的理解,如有不对,请您指正.
from cppprimer.
@pyb1993 你说的是对的, 应该是参数个数为 0 的时候报错的。
from cppprimer.
Related Issues (20)
- ex16_29 include error file,It compile failed HOT 2
- about 16.2.7 HOT 2
- Exercise 7.36
- Exercise 6.53
- Exercise 5.3 correct answer HOT 1
- Ex 6_8 HOT 1
- Ex 6_9 (added #include "fact.cpp")
- Ex 6_10 (added "return 0;")
- Exercise 13.37
- Answer to Exercises 3.37 is not entirely true.
- Ex16.49
- The new soulution of Exercise 5.12
- Ex.7.53 will not compile under the C++14 standard
- #include<exception>
- ex7_22.h 'class' instead of 'struct'
- Bug report exercise 16.12
- An error in exercise 16.28, in file <unique_pointer.h>
- Small modification for answer of Exercise 3.9 - mention `s` is a empty string
- Exercise 9.28(The loop may not stop)
- terminate called after throwing an instance of 'std::bad_alloc
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cppprimer.