我不明白应该如何使用以下功能。当我调用A::f
时,我可以省略模板参数,但我不明白为什么。
template <typename... Args>
struct A
{
template <Args...>
void f() {}
};
int main()
{
A<int, bool> a;
a.f();
}
具体来说,template <Args...>
是什么意思,为什么我可以将模板参数从函数调用中移除到f
?
答案 0 :(得分:5)
template<typename ...Args>
是一个可变参数模板。这意味着,您可以指定任意数量的模板类型参数,但我认为您已经知道了这一点。
只要Args...
出现在模板代码中,它就会解压缩(“展开”)到实例化的类型。在您的示例中,这是 int, bool
。因此,当完全展开时,您的班级将成为这个定义:
struct A<int, bool>
{
template <int, bool>
void f() {}
};
这意味着,A<int,bool>::f()
再次被模板化(参数被解压缩为到另一个模板声明,就像你所说的那样),但这次使用非类型模板参数的类型为int
和bool
(它们是匿名的),因此您可以实例化f()
,例如:
a.f<1, true>();
不幸的是,g++
似乎有一个错误,won't accept这段代码,而accepts代码。
clang
接受这两个代码。我希望在您的代码中,clang不关心int
和bool
模板参数是否被省略,但是在指定它们时它不会抱怨(与g++
相反) )。
用法示例:
如果要使用指定的值,则它们不能是匿名的(显然)。例如,您可以在f()
中提供一个格式字符串,用于“printf”模板值,如下所示:
template <Args ...values>
void f(const char *fmt) {
std::printf(fmt, values...);
}
然后,以下代码
A<int> a;
a.f<42>("The answer is %d!\n");
将打印:
The answer is 42!
但是,使用上面的语法(Args...
扩展为匿名非类型模板参数),模板参数基本上是无用的。
如果没有指定值,它仍会编译(这让我感到惊讶!)并打印出未初始化的int
值。
答案 1 :(得分:0)