11

考虑这个函数模板:

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

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

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

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

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


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

4

1 回答 1

14

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


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

不在现行标准中。

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

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

正如Nicol Bolas在对问题的评论中正确指出的那样,词法顺序意味着将在参数类型之后替换尾随返回类型,如此实时示例中所示。

于 2013-03-17T15:11:22.683 回答