我不明白应该如何使用以下功能.当我调用A :: f时我可以省略模板参数,但我不明白为什么.
template <typename... Args> struct A { template <Args...> void f() {} }; int main() { A<int,bool> a; a.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似乎有一个bug和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值.