我可以扩展一个参数包并用它定义一个参数列表吗?
Can I expand a parameters pack and define an arguments list with it?
从 [temp.variadic](工作草案)开始,在我看来,在定义另一个模板 class 或函数的参数列表时,可以扩展参数包。
考虑以下 class:
template<typename... T>
struct S {
template<T... I>
void m() {}
};
int main() {
S<int, char> s;
// ...
}
目的是 捕获 用于特化模板的类型 class S
并使用它们定义非类型参数的参数列表对于成员方法 m
(当然,T
仅限于几种类型,但这不是问题的论点)。
这是法典吗?我可以按照我使用的方式使用参数包还是我误解了标准(很确定确实如此)?
为了向问题添加更多细节,以下是一些主要编译器的实验结果:
s.m<0, 'c'>()
: clang v3.9 compiles it, GCC v6.2 and GCC v7 return 一个错误。
s.m<0>();
: clang v3.9 compiles it, GCC v6.2 returns an error and GCC v7 使用 ICE 停止编译。
s.m<>();
: clang v3.9, GCC v6.2 and GCC v7 编译没有错误。
至少,编译器似乎和我一样困惑。
模板S
的定义和S<int, char>
的实例化是有效的。
参见 [temp.param]/15:"A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded parameter packs is a pack expansion."
这意味着 template<T ...I>
可以表示两种不同的事情之一:如果 T
是非包类型,那么它声明一个普通参数包,接受任意数量的 T
s。但是,如果 T
包含未扩展的参数包,则在实例化外部模板时,参数声明将扩展为参数序列。
您对 m
的第一次调用有效,但对 m
的第二次和第三次调用格式不正确
S<int, char>
的实例化如下所示:
template<>
struct S<int, char> {
template<int I[=10=], char I>
void m() {}
};
(其中 I[=20=]
和 I
是包的第一片和第二片 I
)。
因此(因为 I[=20=]
和 I
都不能从对 m
的调用中推导出来),s.m<0,'c'>()
是有效的,但是 s.m<0>()
和 s.m<>()
格式错误。
从 [temp.variadic](工作草案)开始,在我看来,在定义另一个模板 class 或函数的参数列表时,可以扩展参数包。
考虑以下 class:
template<typename... T>
struct S {
template<T... I>
void m() {}
};
int main() {
S<int, char> s;
// ...
}
目的是 捕获 用于特化模板的类型 class S
并使用它们定义非类型参数的参数列表对于成员方法 m
(当然,T
仅限于几种类型,但这不是问题的论点)。
这是法典吗?我可以按照我使用的方式使用参数包还是我误解了标准(很确定确实如此)?
为了向问题添加更多细节,以下是一些主要编译器的实验结果:
s.m<0, 'c'>()
: clang v3.9 compiles it, GCC v6.2 and GCC v7 return 一个错误。s.m<0>();
: clang v3.9 compiles it, GCC v6.2 returns an error and GCC v7 使用 ICE 停止编译。s.m<>();
: clang v3.9, GCC v6.2 and GCC v7 编译没有错误。
至少,编译器似乎和我一样困惑。
模板S
的定义和S<int, char>
的实例化是有效的。
参见 [temp.param]/15:"A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded parameter packs is a pack expansion."
这意味着 template<T ...I>
可以表示两种不同的事情之一:如果 T
是非包类型,那么它声明一个普通参数包,接受任意数量的 T
s。但是,如果 T
包含未扩展的参数包,则在实例化外部模板时,参数声明将扩展为参数序列。
您对 m
的第一次调用有效,但对 m
的第二次和第三次调用格式不正确
S<int, char>
的实例化如下所示:
template<>
struct S<int, char> {
template<int I[=10=], char I>
void m() {}
};
(其中 I[=20=]
和 I
是包的第一片和第二片 I
)。
因此(因为 I[=20=]
和 I
都不能从对 m
的调用中推导出来),s.m<0,'c'>()
是有效的,但是 s.m<0>()
和 s.m<>()
格式错误。