当前的标准草案包含此内容(参见本段的最后一句): “当函数参数包出现在非推导上下文 ([temp.deduct.type]) 中时,永远不会推导该包的类型。”
现在,包永远不会被推导是什么意思?如果用户没有指定pack的值,也没有推导出来,难道不是编译失败吗?
当前的编译器处理这种情况,将包定义为空。
这是草稿中的一个精简的示例:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x, y, z); // error: Types is not deduced
}
这无法编译。但是,如果我将示例修改为仅使用 1 个参数,则该示例将编译:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x); // compiles
}
标准中是否有任何内容规定在这种情况下,包装应该是空的?为什么这不是编译错误?
我明白,在后一个例子中,很明显
Types
是空的,因为这是使编译成功的唯一方法。但是,在前面的示例中,“x, y”部分对应于 Types
也应该是显而易见的。我知道, Types
没有被推导出来,所以这个例子不应该编译。那么第二个例子如何编译呢?
Types
在这里也没有推导,所以如果我们考虑“错误:类型未推导”注释(这使得示例无法编译),这也应该使示例格式错误。
开头引用的引用听起来不应该像:“当函数参数包出现在非推导上下文([temp.deduct.type])中时,该包被推导为空。” (这当然看起来有点奇怪,因为它定义了在非推导上下文中推导的东西,但这不是这里发生的事情吗?)
注意:之前也有过类似的问题。但我认为我的问题更明确,并且包含当前草案中的引用(当时没有引用该引用),所以我认为最好提出一个新问题。
当函数参数包处于非推导上下文中时,这意味着编译器无法根据提供的参数确定该包的类型。这种情况下,如果没有推导pack,也不会导致编译错误;相反,它被视为空包。
在第一个使用
g1(x, y, z)
的示例中,编译器无法推断 Types
的类型,因为它处于非推导上下文中(由于包后存在 T1
)。这会导致编译错误,因为它需要为 Types
推导出至少一种类型。
在
g1(x)
的第二个示例中,Types
没有参数,因此很明显 Types
必须为空。编译器允许这样做,因为它可以从逻辑上得出结论:没有类型可以推断。
该标准没有明确指出在此上下文中包应该为空,但暗示如果无法推断出任何类型,则包将被视为空,这使得代码可以无错误地编译。因此,虽然看起来可能令人困惑,但语言的规则允许这种行为,并且它与编译器处理这些情况的方式一致。