考虑这个功能模板:
template<typename T>
typename soft_error<T>::type foo(T, typename hard_error<T>::type)
{ }
在调用T
的第一个参数的类型中推导出类型foo()
后,编译器将继续替换T
并实例化函数签名。
如果首先执行返回类型的替换,导致简单的替换失败,编译器将在计算过载集并搜索其他可行的重载(SFINAE)时丢弃此函数模板。
另一方面,如果首先发生第二个函数参数的替换,导致硬错误(例如,由于非直接上下文中的替换失败),整个编译将失败。
问题: 对于函数参数和返回类型的替换顺序是否有任何保证?
注意: This example似乎表明在所有主要编译器上(VC11已单独测试并给出相同的结果),在替换参数类型之前会替换返回类型。
答案 0 :(得分:14)
[注意:这本来不是一个自我回答的问题,但我在制作问题时碰巧找到了解决方案]
对于函数参数和返回类型的替换顺序是否有任何保证?
不符合现行标准。
但是,this Defect Report(由Xeo提供)表明确实是这种情况。以下是C ++ 11标准第14.8.2 / 7段的新措辞(已成为n3485 draft的一部分):
替换发生在函数类型和模板中使用的所有类型和表达式中 参数声明。表达式不仅包括常量表达式,例如出现在其中的常量表达式 数组边界或非类型模板参数以及一般表达式(即非常量表达式) 内部sizeof,decltype和其他允许非常量表达式的上下文。 替换进行 在词汇顺序中,当遇到导致演绎失败的条件时停止。 [...]
正如Nicol Bolas在问题的评论中正确指出的那样,词法顺序意味着在参数类型之后将尾随的返回类型替换为,如this live example所示。