这两个可变参数函数之间的本质区别是什么?

问题描述:

我通过一个简单的可变参数模板功能已经been frustrated这两个可变参数函数之间的本质区别是什么?

constexpr size_t num_args() { 
    return 0; 
} 

template <typename H, typename... T> 
constexpr size_t num_args() { 
    return 1 + num_args <T...>(); 
} 

int main() { 
    std :: cout << num_args <int, int, int>(); 
} 

以上不编译,见上面链接的细节问题and followup,但下面的函数编译

template <typename T, typename... Args> void foo (T, Args...); 

template <typename... Args> void foo (int, Args...); 

void foo() {} 

template <typename... Args> 
void foo (int x, Args... args) 
{ 
    std :: cout << "int:" << x; 
    foo (args...); 
} 

template <typename T, typename... Args> 
void foo (T x, Args... args) 
{ 
    std :: cout << " T:" << x; 
    foo (args...); 
} 

foo (int (123), float (123)); // Prints "int:123 T:123.0" 

似乎都要使用相同的语言机制,但为什么第二个好的时候第一个不好呢?

+0

没关系,那不是真的重复,抱歉。 –

+2

请注意'num_args'可以做为sizeof ...(Args)'。 – GManNickG

+0

不错的提示,GMan,谢谢,但是这段代码是为了演示可变参数的语法。 – spraff

我开始认为,不同的是,

foo (args...); 

漏洞过载而

num_args <T...>(); 

利用专业化。

重载可以处理基本情况,但专业化不能用于函数模板(但它可以用于类),这就是为什么auxilliary_class<Args...>::value是惯用的。

不同的是,第一个函数

constexpr size_t num_args() { 
    return 0; 
} 

不是一个模板,所以它可以永远这样调用

num_args <T...>();