我可以展开一个参数包并定义一个参数列表吗?
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
仅限于几种类型,但这不是问题的参数)。
这是法律法规吗?我可以按照我使用的方式使用参数包吗?还是我误解了标准(非常确定确实是这种情况)?
为了给这个问题添加更多的细节,这里有一些来自主要编译器的实验结果:
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<int, char>
的实例化是有效的
参见[temp.param]/15: "一个模板参数包是参数声明,其类型包含一个或多个未展开的参数包是一个扩展包。"
这意味着template<T ...I>
可以表示两种不同的情况之一:如果T
是非包类型,那么它声明一个普通参数包,接受任意数量的T
。但是,如果T
包含一个未展开的参数包,那么在外部模板实例化时,参数声明将被展开为一个参数序列。
第一次调用m
是有效的,但是第二次和第三次调用m
是错误的
S<int, char>
的实例化如下:
template<>
struct S<int, char> {
template<int I$0, char I$1>
void m() {}
};
(其中I$0
和I$1
是包I
的第一个和第二个片)。
因此(因为I$0
和I$1
都不能从对m
的调用中推导出来),s.m<0,'c'>()
是有效的,而s.m<0>()
和s.m<>()
是病态的。
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何制作一个将函数作为参数的类方法
- 修改函数中的指针(将另一个指针作为参数传递)
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 构造函数在退出函数时无法初始化一个参数
- 在C++中声明一个函数时,它需要有函数本身的参数吗
- visual是否可以在c++中创建一个接收无限数量相同类型(或至少相当数量)参数的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 运算符重载:"operator+"必须采用零个或一个参数
- 是否可以在C++中有一个"generic"模板参数,该参数可以是非类型模板参数或类型?
- 如果需要转换,我可以在读取参数的同时将其移动到另一个参数吗?
- 如何在另一个函数中使用返回值作为参数?
- 如果模板参数是另一个模板的实例化,则键入特征测试
- 将参数一个接一个地传递,或通过将它们包裹在数组,结构或元组中
- 如何给一个参数一个由其他参数的函数确定的默认值
- C++如何给一个参数一个特定的枚举,它可以是
- 如果我在默认构造函数中放了一个参数,但给了这个参数一个默认值,它还是一个默认构造函数吗
- 为什么在c++中给typename模板参数一个默认值0 ?