我不明白应该如何使用以下功能。当我打电话时,A::f
我可以省略模板参数,但我不明白为什么。
template <typename... Args>
struct A
{
template <Args...>
void f() {}
};
int main()
{
A<int, bool> a;
a.f();
}
具体来说,这是什么template <Args...>
意思,为什么我可以将模板参数排除在函数调用之外f
?
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++
似乎有一个错误并且不会接受这段代码,而它会接受您的代码。
clang
接受这两个代码。我希望在您的代码中,clang 不在乎是否省略了int
和bool
模板参数,但是在指定它们时它也不会抱怨(与 相比g++
)。
使用示例:
如果要使用指定的值,它们不能是匿名的(显然)。例如,您可以提供f()
用于“打印”模板值的格式字符串,如下所示:
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
值。