7

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

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

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

具体来说,这是什么template <Args...>意思,为什么我可以将模板参数排除在函数调用之外f

4

2 回答 2

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++似乎有一个错误并且不会接受这段代码,而它会接受您的代码。

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

于 2013-05-29T20:00:17.643 回答
0

您可以省略模板参数的原因是因为 c++11 具有模板参数推导template<args ...>是一个可变参数模板,它基本上是一组可能不同的类型名。该网站解释了模板参数的省略。从进一步阅读非类型模板参数的推论,编译器可以推断出,我相信编译器意识到它们从未被使用过(至少使用 clang)并基于此进行推论,阅读推论的非类型模板参数网站的一部分

于 2013-05-29T20:00:37.693 回答