col*_*tam 5 c++ language-lawyer variadic-templates template-argument-deduction c++17
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;
Run Code Online (Sandbox Code Playgroud)
clang 接受代码,推导Types = {long, unsigned}, Outer = {O1, O2}, Inner={1L, 2U}. 从结构上看,这似乎是正确的。
gcc 因推导失败而拒绝该代码。有趣的是,它确实接受 ifO2更改为采用long非类型模板参数,这对我来说似乎不一致。它表明类型可以扩展 ifTypes = {long, long}但不能扩展 if Types = {long, unsigned}。
但是,从标准中我不清楚哪个编译器是正确的。核心问题是:在 表示的行上XXX,将参数包作为模板模板参数的非类型模板参数的类型是否有效?它应该像 clang 声称的那样扩展吗?
它无效,因为:
类型参数包不能在其自己的参数子句中扩展。
如果模板参数是在其可选标识符之前带有省略号的类型参数,或者是声明包 ([dcl.fct]) 的参数声明,则模板参数是模板参数包。模板参数包是一种参数声明,其类型包含一个或多个未扩展的包,该模板参数包是包扩展。...作为包扩展的模板参数包不得扩展在同一template-parameter-list中声明的模板参数包。
因此,请考虑以下无效示例:
template<typename... Ts, Ts... vals> struct mytuple {}; //invalid
Run Code Online (Sandbox Code Playgroud)
上面的例子是无效的,因为模板类型参数包Ts不能在自己的参数列表中扩展。
出于同样的原因,您的代码示例无效。
| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |