考虑下面的代码,我不明白为什么必须定义print的空函数.
#include <iostream>
using namespace std;
void print()
{
}
template <typename T, typename... Types>
void print (const T& firstArg, const Types&... args)
{
cout << firstArg << endl; // print first argument
print(args...); // call print() for remaining arguments
}
int main()
{
int i=1;
int j=2;
char c = 'T';
print(i,"hello",j,i,c,"word");
}
Run Code Online (Sandbox Code Playgroud)
Gam*_*per 13
正确的方式:
变量模板与induction数学概念严格相关.
编译器解析以下函数调用
print('a', 3, 4.0f);
Run Code Online (Sandbox Code Playgroud)
成
std::cout<< 'a' <<std::endl;
print(3, 4.0f);
Run Code Online (Sandbox Code Playgroud)
这解决了
std::cout<< 'a' <<std::endl;
std::cout<< 3 <<std::endl;
print( 4.0f);
Run Code Online (Sandbox Code Playgroud)
这解决了
std::cout<< 'a' <<std::endl;
std::cout<< 3 <<std::endl;
std::cout<< 4.0f <<std::endl;
print();
Run Code Online (Sandbox Code Playgroud)
此时,它搜索匹配为空函数的函数重载.
罪魁祸首是,对于每种可能的参数组合,您必须只有1个功能.
错误1:
执行以下操作将是一个错误
template< typename T>
void print( const T& arg) // first version
{
cout<< arg<<endl;
}
template <typename T, typename... Types>
void print (const T& firstArg, const Types&... args) // second version
{
cout << firstArg << endl; // print first argument
print(args...); // call print() for remaining arguments
}
Run Code Online (Sandbox Code Playgroud)
因为当你调用print编译器时不知道要调用哪个函数.
是否print(3)指的是"第一"或"第二"的版本?两者都是有效的,因为第一个有1个参数,第二个也可以接受一个参数.
print(3); // error, ambiguous, which one you want to call, the 1st or the 2nd?
Run Code Online (Sandbox Code Playgroud)
错误2:
无论如何,以下将是一个错误
// No empty function
template <typename T, typename... Types>
void print (const T& firstArg, const Types&... args)
{
cout << firstArg << endl; // print first argument
print(args...); // call print() for remaining arguments
}
Run Code Online (Sandbox Code Playgroud)
实际上,如果单独使用它而没有编译器就可以
print('k', 0, 6.5);
Run Code Online (Sandbox Code Playgroud)
这解决了
std::cout<<'k'<<std::endl;
print(0, 6.5);
Run Code Online (Sandbox Code Playgroud)
这解决了
std::cout<<'k'<<std::endl;
std::cout<< 0 <<std::endl;
print( 6.5);
Run Code Online (Sandbox Code Playgroud)
这解决了
std::cout<<'k'<<std::endl;
std::cout<< 0 <<std::endl;
std::cout<< 6.5 <<std::endl;
print(); //Oops error, no function 'print' to call with no arguments
Run Code Online (Sandbox Code Playgroud)
正如您在上次尝试中看到的那样,编译器尝试print()不带参数进行调用.但是,如果这样的函数不存在则不会被调用,这就是为什么你应该提供那个空函数(不用担心,编译器会优化代码,所以空函数不会降低性能).
Gar*_*365 10
如果您没有空print功能,请设想一个带有2个参数的呼叫:
oups,print()不存在,因为只print存在至少一个参数!所以你需要一个print没有参数.
print 没有任何参数是你最后的电话
因为(使用非常"简单"的解释),可变参数模板机制的工作方式类似于递归(它不是递归,但这是理解它的最简单方法),它"消耗"可变参数列表,因此您将不得不定义一个" 停止 "函数,当"消耗"参数列表为" 空 " 时,它将在递归的最后一步重复出现.这是我发现最容易理解这个相当复杂的概念的解释.
在第一步(in main),您将获得一个具有以下参数的函数:(int, const char*, int, int, char, const char*)
然后在可变参数函数本身中慢慢处理可变参数,让你在第二步中(const char*, int, int, char, const char*)依次(int, int, char, const char*)等等......直到你到达最后一个元素(const char*),当你在下一步中处理它时,你最终会得到(),并且编译器需要此函数作为"终止符"
(是的,这是非技术性的,听起来像爷爷青蛙向小青蛙讲故事......)