【发布时间】:2021-09-12 16:15:50
【问题描述】:
来自C++ 模板 - 完整指南第 2 版:
此外,此类参数不能有用地放置在模板参数包之后或出现在部分特化中,因为无法显式指定或推导它们。
template<typename ...Ts, int N> void f(double (&)[N+1], Ts ... ps); // useless declaration because N // cannot be specified or deduced
其中 此类参数 指的是(我认为)与那些永远无法推断的模板参数相对应的模板参数。 IE。上例中N是不能推导的参数,因为N+1“太复杂推导不了”。
但是为什么不能指定它呢?我知道不可能指定N 并推导出...Ts,但为什么不能全部指定呢?换句话说,通过以下方式指定Ts=[int] 和N=2 有什么问题?
double x[3];
f<int,2>(x,1);
【问题讨论】:
-
...太贪心了,它也消耗了2。当编译器意识到2不是一种类型时,为时已晚。以其他方式做在理论上是可能的,但可能会使已经相当复杂的解析器复杂化。 -
哦,好吧...由于模板参数的种类(非类型、类型和模板)很好分离,我没想到到时候可能是一个论点。例如,为什么编译器在查找类型时要消耗 2?
-
在一般情况下,它们并没有很好地分开。例如,您可以将
A设为类型、using A = int;或非类型constexpr int A = 2;。那么编译器会用f<int, A>做什么呢?我的猜测是解析器甚至不会尝试在这里进行分析。 -
我知道这是一个纯粹的理论问题,但值得一提的是,在实践中,这很少会成为问题,因为您可以将参数包放在模板参数列表的末尾。跨度>
-
@Enlico 我明白了。也许即使不完全相关的帖子也能稍微澄清一下。在您的示例中,如果编译器可以区分类型模板和非类型模板,它会起作用,但在其他情况下它可能会出现问题。因此标准对此非常严格:模板参数包之后的所有参数,无论非类型的类型必须是默认的还是可扣除的。
标签: c++ templates c++17 language-lawyer template-meta-programming