将参数包解压缩到另一个模板声明中意味着什么?

时间:2013-05-29 19:46:05

标签: c++ c++11

我不明白应该如何使用以下功能。当我调用A::f时,我可以省略模板参数,但我不明白为什么。

template <typename... Args>
struct A
{
    template <Args...>
    void f() {}
};

int main()
{
    A<int, bool> a;
    a.f();
}

具体来说,template <Args...>是什么意思,为什么我可以将模板参数从函数调用中移除到f

2 个答案:

答案 0 :(得分:5)

template<typename ...Args>是一个可变参数模板。这意味着,您可以指定任意数量的模板类型参数,但我认为您已经知道了这一点。

只要Args...出现在模板代码中,它就会解压缩(“展开”)到实例化的类型。在您的示例中,这是 int, bool 。因此,当完全展开时,您的班级将成为这个定义:

struct A<int, bool>
{
    template <int, bool>
    void f() {}
};

这意味着,A<int,bool>::f()再次被模板化(参数被解压缩为到另一个模板声明,就像你所说的那样),但这次使用非类型模板参数的类型为intbool(它们是匿名的),因此您可以实例化f(),例如:

a.f<1, true>();

不幸的是,g++似乎有一个错误,won't accept这段代码,而accepts代码。

clang接受这两个代码。我希望在您的代码中,clang不关心intbool模板参数是否被省略,但是在指定它们时它不会抱怨(与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)

你可以保留模板参数的原因是因为c ++ 11有模板参数推论template<args ...>是一个可变参数模板,它基本上是一组可能不同的类型名。这个website解释了模板参数的遗漏。从进一步阅读到非类型模板参数的推导,编译器可以推导出来我认为编译器意识到它们从未被使用过(至少有clang)并且基于它进行了推论,请阅读推导非类型模板参数website

的一部分