问题 类型扣除后,功能模板中的替换顺序是否有任何保证?


考虑这个功能模板:

template<typename T>
typename soft_error<T>::type foo(T, typename hard_error<T>::type)
{ }

演绎后的类型 T 从调用中的第一个参数的类型 foo(),编译器将继续替换 T 并实例化函数签名。

如果首先执行返回类型的替换,导致简单的替换失败,编译器将在计算过载集并搜索其他可行的重载(SFINAE)时丢弃此函数模板。

另一方面,如果首先发生第二个函数参数的替换,导致硬错误(例如,由于非直接上下文中的替换失败),则整个编译将失败。

题:  对于函数参数和返回类型的替换顺序是否有任何保证?


注意:  这个例子 似乎表明,在所有主要编译器(VC11分别进行测试并给出相同的结果)中,在替换参数类型之前会替换返回类型。


9431
2018-03-17 15:11


起源

注意 迟到 - 指定返回类型会改变事物。 - Nicol Bolas
@NicolBolas:是的,那是因为替换实际上意味着以词汇顺序发生 - 顺便说一句Xeo正确地指出这不是当前标准规定的行为,所以我纠正了我的答案 - Andy Prowl


答案:


[注意:这本来不是一个自我回答的问题,但我碰巧在制作问题时找到了解决方案]


对于函数参数和返回类型的替换顺序是否有任何保证?

不符合现行标准。 

然而, 这个缺陷报告 (由...提供) XEO)表明这确实是这样的。以下是C ++ 11标准第14.8.2 / 7段的新措辞(已成为该标准的一部分) n3485选秀):

替换发生在函数类型和模板中使用的所有类型和表达式中   参数声明。表达式不仅包括常量表达式,例如出现的表达式   数组边界或非类型模板参数以及一般表达式(即非常量表达式)   内部sizeof,decltype和其他允许非常量表达式的上下文。 替换继续进行   在词汇顺序中,当遇到导致演绎失败的条件时停止。 [...]

正如所指出的那样 尼科尔博拉斯 在对问题的评论中, 词汇顺序 表示将替换尾随返回类型  参数类型,如图所示 这个实例


14
2018-03-17 15:11



那太好了。谢谢你分享这个。 +1到Q&A。 - Nawaz