这是我在可变参数模板中的第一个代码:
void print_f()
{
}
template<typename T, typename ... ARG>
void print_f(const T& a, ARG... C)
{
std::cout<<a;
print_f(C...); // -> at this line I want to know
std::cout<<std::endl;
}
当我对print_f(C...);
进行递归调用时,究竟发生了什么?我的意思是
模板参数包C
得到解压缩,如何在可变参数模板中完成函数参数推导,匹配是如何完成的?
任何人都可以解释一些基础知识吗?
修改:通常在模板类中,如
template <typename T> class x{
public:
T aa; // can declare variable of type T
};
但在可变参数模板中:
template<typename T, typename ... ARG>
void print_f(const T& a /* , ARG... C -> if remove this */ )
{
std::cout<<a;
ARG... C // and put it here , we can't do this, why?
print_f(C...);
std::cout<<std::endl;
}
答案 0 :(得分:2)
我认为你的第一个printf重载也必须是模板,但我不是百分之百确定。
无论如何,它或多或少都是这样的:
printf("APPLE", 10, '@', 9.0);
// this calls printf(const char*, int, char, double)
// with T=const char*, and ARG={int, char, double}
printf(const char* a, ARG ... C) {
std::cout<<a; // this displays "APPLE"
print_f(C...);
// this calls printf(int, char, double)
// with T=int, and ARG={char, double}
printf(int a, ARG ... C) {
std::cout<<a; // this displays 10
print_f(C...);
// this calls printf(char, double)
// with T=char, and ARG={double}
printf(char a, ARG ... C) {
std::cout<<a; // this displays '@'
print_f(C...);
// this calls printf(double)
// with T=double, and ARG={}
printf(double a, ARG ... C) {
std::cout<<a; // this displays 9.0
print_f(C...);
// this calls printf()
printf() {
}
std::cout<<std::endl;
std::cout<<std::endl;
std::cout<<std::endl;
std::cout<<std::endl;
还应该注意,使用您的代码,所有值都出现在同一行,后面跟着许多空行。我想你想在递归之前endl
。
根据您的编辑:在您的假设函数template<typename T, typename ... ARG>
void print_f(const T& a)
中,除非您自己指定ARG,否则您将无法调用此函数,因为它无法从函数参数类型中推断出,因为ARG不再位于参数。
此外,无法实例化可变参数模板,因为它们不是类型,它们是一组类型。如果你真的想要实例化一些东西,你可以使用一个元组:std::tuple<ARGS> C;
,但是所有的对象都是默认构造的,因为你没有将参数传递给要构造的函数。
答案 1 :(得分:0)
并把它放在这里,我们不能这样做,为什么?
因为C ++ 0x标准不允许你。它不允许您解压缩堆栈上的模板参数。或者进入班级的数据列表。或任何那种性质。
它允许您将类型解压缩到参数列表中,以便函数可以获取可变数量的参数。