我可以扩展一个参数包和定义一个参数列表吗? [英] Can I expand a parameters pack and define an arguments list with it?
问题描述
从 [temp.variadic] (工作草稿),它似乎
考虑下面的类:
template< typename ... T>
struct S {
template< T ... I>
void m(){}
};
int main(){
S< int,char> s;
// ...
}
捕获用于专门化模板类 S
的类型,并使用它们为成员方法定义非类型参数的参数列表 m
( T
仅限于几种类型,当然,但这不是问题的参数)。
这是法律代码吗?
p>为了给问题添加更多细节,下面是主要编译器的一些实验的一些结果:
-
s.m< 0,'c'>()
: clang v3.9 编译它, GCC v6.2 和 GCC v7 返回错误。 -
s.m< 0>();
: clang v3.9 编译, GCC v6.2 返回错误, GCC v7 停止使用ICE的编译。 -
s.m < >();
: clang v3.9 , GCC v6.2 和 GCC v7 编译时没有错误。
至少,编译器似乎和我一样困惑。
模板 S
的定义, S
请参见[temp.param ] / 15:类型包含一个或多个未展开参数包的模板参数包是参数声明是一个包展开。
这意味着模板< T ... I>
可以表示两种不同的情况之一:if T
非包装类型,那么它声明一个正常的参数包,接受任何数量的 T
。但是,如果 T
包含未展开的参数包,则在外部模板实例化时,参数声明会扩展为参数序列。
您对 m
的第一次调用有效,但您第二次和第三次调用 m $ c $
S< int,char>
的实例化:
模板<>
struct S< int,char> {
template< int I $ 0,char I $ 1>
void m(){}
};
(其中 I $ 0
和 I $ 1
是包的 I
的第一和第二个切片。
因此(因为 I $ 0
和 I $ 1
都不能从调用 有效,但
s.m <0>()和
s.m<>()
是错误的。
From [temp.variadic] (working draft) it seemed to me that a parameters pack can be expanded while defining an arguments list of another template class or function.
Consider the following class:
template<typename... T>
struct S {
template<T... I>
void m() {}
};
int main() {
S<int, char> s;
// ...
}
The intent is to capture the types used to specialize the template class S
and use them to define an arguments list of non-type parameters for the member method m
(T
is limited to a few types, of course, but this isn't the argument of the question).
Is this legal code? Can I use a parameter pack the way I used it or am I misinterpreting the standard (pretty sure that's the case indeed)?
In order to add more details to the question, here are some results from a few experiments with the major compilers:
s.m<0, 'c'>()
: clang v3.9 compiles it, GCC v6.2 and GCC v7 return an error.s.m<0>();
: clang v3.9 compiles it, GCC v6.2 returns an error and GCC v7 stops the compilation with an ICE.s.m<>();
: clang v3.9, GCC v6.2 and GCC v7 compile it with no errors.
At least, compilers seem to be as confused as me.
The definition of the template S
, and the instantiation of S<int, char>
, are valid.
See [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."
This means that template<T ...I>
can mean one of two different things: if T
is a non-pack type, then it declares a normal parameter pack, accepting any number of T
s. However, if T
contains an unexpanded parameter pack, then the parameter declaration is instead expanded into a sequence of parameters when the outer template is instantiated.
Your first call to m
is valid, but your second and third calls to m
are ill-formed
The instantiation of S<int, char>
looks like this:
template<>
struct S<int, char> {
template<int I$0, char I$1>
void m() {}
};
(where I$0
and I$1
are the first and second slices of the pack I
).
Therefore (because neither I$0
nor I$1
can be deduced from a call to m
), s.m<0,'c'>()
is valid but s.m<0>()
and s.m<>()
are ill-formed.
这篇关于我可以扩展一个参数包和定义一个参数列表吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!