使用未扩展的参数包作为模板模板参数的非类型模板参数的类型是否合法?
gcc 和 clang 对于以下代码是否应该编译存在分歧:
template <typename... Args>
struct tuple {};
template <typename>
struct Test;
template <
typename... Types,
template <Types> typename... Outer, // XXX
Types... Inner
>
struct Test<tuple<Outer<Inner>...>> {};
template <long T> struct O1 {};
template <unsigned T> struct O2 {};
Test<tuple<O1<1>, O2<2>>> test;
clang 接受代码,推导出 Types = {long, unsigned}, Outer = {O1, O2}, Inner={1L, 2U}
。从结构上看,这似乎是正确的。
gcc 因推导失败而拒绝该代码。有趣的是,如果将 O2
更改为采用 long
非类型模板参数,它确实接受,这对我来说似乎不一致。它表明如果 Types = {long, long}
则可以扩展 Types,但如果 Types = {long, unsigned}
则不能扩展。
但是,从标准中我不清楚哪个编译器是正确的。核心问题是:在XXX
这一行,模板参数的非类型模板参数的类型为参数包是否有效?它应该像 clang 声称的那样扩展吗?
gcc and clang disagree about whether the following code should compile:
template <typename... Args>
struct tuple {};
template <typename>
struct Test;
template <
typename... Types,
template <Types> typename... Outer, // XXX
Types... Inner
>
struct Test<tuple<Outer<Inner>...>> {};
template <long T> struct O1 {};
template <unsigned T> struct O2 {};
Test<tuple<O1<1>, O2<2>>> test;
clang accepts the code, deducing Types = {long, unsigned}, Outer = {O1, O2}, Inner={1L, 2U}
. Structurally, this seems correct.
gcc rejects the code with a deduction failure. Interestingly, it does accept if O2
is changed to take a long
non-type template parameter, which seems inconsistent to me. It suggests that Types can be expanded if Types = {long, long}
but not if Types = {long, unsigned}
.
However, it's not clear to me from the standard which compiler is correct. The core question is: on the line denoted XXX
, is it valid to have a parameter pack as the type of the template template parameter's non-type template parameter? Should it expand the way that clang claims it does?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它无效,因为:
从 [temp.param]/17 开始:
因此,请考虑以下无效示例:
上面的示例无效,因为模板类型参数包
Ts
无法在其自己的参数列表中扩展。出于同样的原因,您的代码示例无效。
It is not valid because:
As from [temp.param]/17:
So consider the following invalid example:
The above example is invalid because the template type parameter pack
Ts
cannot be expanded in its own parameter list.For the same reason, your code example is invalid.