为什么提供无参数函数模板时,编译器会尝试推论?

发布于 2025-02-05 17:31:41 字数 766 浏览 1 评论 0 原文

template <typename... T>
struct X {
    static_assert(sizeof...(T) != 0);
};

template <typename... T>
void f(const X<T...> &) {}

template <typename T>
void inner() {}

int main() {
    f(inner);
}

在此示例中,静态断言发射。

为什么编译器尝试在这里推论任何东西? 空类型参数列表?

使用

然后,它显然甚至尝试实例化X ( 编译器报告说是一个结构:

使用类模板的使用“内部”需要模板参数

这很有意义。如果参数只是 const x&amp; ,则有

声明类型包含未表达的参数包't'

这也有意义,但是对于结构的情况不太清楚,因为它在callee上报告了问题,而不是在呼叫站点上。

如果参数为 const x&lt; t&gt; &amp; ,乍一看也有些怪异:

忽略候选模板:无法推断模板参数't'。

这些错误是针对Clang 14的,但GCC也报告了类似的错误。

这里的实例化是否由标准指定?如果是这样,怎么样?另外,为什么会导致一个空类型列表?

template <typename... T>
struct X {
    static_assert(sizeof...(T) != 0);
};

template <typename... T>
void f(const X<T...> &) {}

template <typename T>
void inner() {}

int main() {
    f(inner);
}

The static assert fires in this example.

Why does the compiler try to deducing anything here? And then it apparently even tries to instantiate X (with empty type argument list?..)...

Why the error isn't just 'template used without arguments'?..

If I change inner function to be a struct, the compiler reports:

use of class template 'inner' requires template arguments

which makes sense; if the param is just const X &, there's

declaration type contains unexpanded parameter pack 'T'

which also makes sense, however is less clear than the case with struct, because it reports an issue at the callee, not at the call site.

If the param is const X<T> &, the report is also a bit weird at first sight:

candidate template ignored: couldn't infer template argument 'T'.

These errors are for Clang 14, but GCC also reports similar ones.

Is the instantiation here somehow specified by the standard? If so, how? Also, why does it result in an empty type list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

唱一曲作罢 2025-02-12 17:31:41

这主要是由于 ,适用于源名称函数模板并强调我的:

可以从explicit template-arguments 的列表中省略可以从默认的 template-arguments arguments 获得的尾随模板参数尾随的模板参数包其他未能推导的参数包将被推导为模板参数的空序列。如果可以推导所有模板参数,则可能会省略它们;在这种情况下,也可以省略空模板参数列表&lt;&gt; 本身也可以省略。

函数模板名称作为参数意味着它不用于模板参数扣除 f t 未从函数参数列表(innion)和[temp.arg.explicit]/4应用于 t 作为类型的空列表。

现在评估表达式 f(inne)涉及将表达式内部转换为参数类型 const x&lt;&gt;&gt;&amp; 。是否以及如何有效取决于类 x&lt;&gt; 的构造函数,因此模板是实例化的,导致 static_assert 错误,因为模板参数pack确实具有零元素。

This is mostly due to [temp.arg.explicit]/4, applicable when source names a function template, and emphasis mine:

Trailing template arguments that can be deduced or obtained from default template-arguments may be omitted from the list of explicit template-arguments. A trailing template parameter pack not otherwise deduced will be deduced as an empty sequence of template arguments. If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.

The function template name as an argument means it is not used for template argument deduction of f ([temp.deduct.type]/(5.5.3)). So the pack T is not deduced from the function argument list (inner), and [temp.arg.explicit]/4 applies and deduces T as an empty list of types.

Now to evaluate the expression f(inner) involves converting the expression inner to the parameter type const X<>&. Whether and how this is valid depends on the constructors of class X<>, so the template is instantiated, causing the static_assert error since the template parameter pack does have zero elements.

智商已欠费 2025-02-12 17:31:41

因为该参数是指包含函数模板 x 的过载集, 均尝试从中尝试。希望,扣除次数无论如何都会成功(也许是从其他参数中),然后可以从产生的参数类型中得出 x 的模板参数。 (当然,不可能推断出内部的模板参数,但是即使是

template<class T>
T make();

在某些情况下也可以推论的模板参数,因此通常不是徒劳的希望。)

在这里,扣除 f的扣除确实成功 ,用 t 作为空包。 (这很像默认的模板参数。)然后, const x&lt;&gt;&gt; 是参数类型,因此试图构造过载分辨率来构建 x&lt;&gt; 来自 Inner 。显然,这取决于构造函数对于 x&lt;&gt; ,因此该类型已完成并且编译失败。

Because the argument refers to an overload set that contains a function template X, no deduction is attempted from it. The hope is that the deduction will succeed anyway (perhaps from other arguments) and then the template arguments of X can be deduced from the resulting argument type. (Of course, it’s impossible to deduce the template argument for inner, but even that of

template<class T>
T make();

can be deduced in certain contexts, so it’s not in general a vain hope.)

Here, deduction for f does succeed vacuously, with T as an empty pack. (This is much like a default template argument.) Then const X<>& is the parameter type, and so overload resolution is attempted to construct an X<> from inner. That obviously depends on the constructors for X<>, so that type is completed and the compilation fails.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文