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?
发布评论
评论(2)
这主要是由于 ,适用于源名称函数模板并强调我的:
函数模板名称作为参数意味着它不用于模板参数扣除
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:
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 packT
is not deduced from the function argument list(inner)
, and [temp.arg.explicit]/4 applies and deducesT
as an empty list of types.Now to evaluate the expression
f(inner)
involves converting the expressioninner
to the parameter typeconst X<>&
. Whether and how this is valid depends on the constructors of classX<>
, so the template is instantiated, causing thestatic_assert
error since the template parameter pack does have zero elements.因为该参数是指包含函数模板 x 的过载集, 均尝试从中尝试。希望,扣除次数无论如何都会成功(也许是从其他参数中),然后可以从产生的参数类型中得出 x 的模板参数。 (当然,不可能推断出
内部
的模板参数,但是即使是在某些情况下也可以推论的模板参数,因此通常不是徒劳的希望。)
在这里,扣除
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 ofcan be deduced in certain contexts, so it’s not in general a vain hope.)
Here, deduction for
f
does succeed vacuously, withT
as an empty pack. (This is much like a default template argument.) Thenconst X<>&
is the parameter type, and so overload resolution is attempted to construct anX<>
frominner
. That obviously depends on the constructors forX<>
, so that type is completed and the compilation fails.