在VisualStudio 2015更新1中,我们为C++ 11核心语言特征表达式SFIEAE添加了部分支持。
什么是SFINAE?
斯菲纳 是“替换失败不是错误”的缩写。其思想是,当编译器在重载解析期间尝试专门化函数模板时,只要存在其他有效的候选函数,如果专门化失败就可以了。C++ 11引入了诸如DeCype和CistExpR等特性,在模板参数推导和替换过程中有更常见的表达式。C++标准委员会澄清了C++ 11中表达式的sFANE规则。
为什么部分实现表达式SFINAE?
是的 部分原因如下:
- 我们正在逐步完善Visual C++编译器的解析器,着眼于表达式sFANE特征的完全一致性。有关这项工作的一些见解,请参阅 微软C/C++编译器的恢复 作者:吉姆·斯普林菲尔德。
- 在VisualStudio2015 RTM中,我们没有为表达式实现SFINAE规则,并且对表达式SFINAE的支持有限。对表达式sFANE的改进将从VisualStudio 2015更新1开始,并将逐步地符合C++ 11标准。
我们做了什么?
我们仍在使用旧的基于令牌流的方法,并且还没有使用递归下降解析树,因此仍然存在一些问题 不支持的方案 . 对于此版本,我们修复了以下问题:
感谢所有提供反馈的人!
更新1中支持的方案
有四种支持的方案。
在函数模板的模板类型参数或函数参数类型的默认参数中使用依赖表达式:
#包括 <类型特征>
模板 < 类别名 T >
班 A
{
公众的 :
明确的 A( T 常数 &);
模板 < 类别名 U , 类别名 五 =标准: 启用u如果u t < !标准: 你是一样的吗 < U , T >●价值观 > >
明确的 A( U 常数 &);
};
模板 < 类别名 T >
班 B
{
公众的 :
枚举 {M=1};
模板 < 内景 我>
无效 食品(标准: 启用u如果u t < (I==M) >* = 空PTR );
模板 < 内景 我>
无效 食品(标准: 启用u如果u t < (我!=米) >* = 空PTR );
模板 < 内景 我>
无效 g(){foo();} //VS2015 RTM给出错误C2668:“B
};
无效 f级( B < 内景 > b )
{
b .g<0>();
A < 内景 >(0);
}
在类模板的模板类型参数的默认参数中使用依赖decltype:
#包括 <类型特征>
模板 < 班 C , 类别名 T = 脱模 (& C :(男)>
结构 M
{
类型定义 T 类型 ;
};
结构 失败类型 {};
模板 < 类别名 T > 类别名 M < T >:: 类型 试验( 无效 *);
模板 < 类别名 T > 失败类型 试验(…);
结构 S1级 { 内景 m、 };
结构 S2级 { };
静态u断言 (!标准: 你是一样的吗 < 脱模 (试验)< S1级 >( 空PTR )), 失败类型 >●价值观, “失败” ); //VS2015 RTM故障
静态u断言 (标准: 你是一样的吗 < 脱模 (试验)< S2级 >( 空PTR )), 失败类型 >●价值观, “失败” );
在模板非类型参数的类型中使用依赖decltype:
#包括 <类型特征>
使用 命名空间 标准;
模板 < 类别名 T , 类别名 启用u if < 你是空的吗 < 脱模 (十二)< T >().f() )>●价值观, 内景 >:: 类型 V=0>
烧焦 f级( T ); //VS2015 RTM无法编译此声明
短的 f(…);
结构 S1级 { 无效 f();};
结构 S2级 { 内景 f();};
结构 S3级 { };
静态u断言 ( 大小 (f)( S1级 {})) == 大小 ( 烧焦 ), “失败” );
静态u断言 ( 大小 (f)( S2级 {})) == 大小 ( 短的 ), “失败” );
静态u断言 ( 大小 (f)( S3级 {})) == 大小 ( 短的 ), “失败” );
在类模板的部分专门化的模板参数中使用依赖decltype:
#包括 <类型特征>
模板 < 班 T , 班 五 = 无效 > 结构 你完成了吗 :标准:: 错误的u类型 {};
模板 < 班 T > 结构 你完成了吗 < T , 脱模 ( 无效 ( 大小 ( T ))) >:标准:: 真u类型 {};
结构 S1级 {};
结构 S2级 ;
静态u断言 ( 你完成了吗 < S1级 >●价值观, “失败” ); //VS2015 RTM故障
静态u断言 (! 你完成了吗 < S2级 >●价值观, “失败” );
更新1中不支持的方案
目前有6种不受支持的方案。有些有解决办法。
声明除decltype中的不同表达式外具有相同签名的两个函数。 如果您试图构建Boost库,就会遇到这个问题。因为我们将表达式捕获为令牌流,所以无法可靠地比较不同的表达式(例如,一个问题是我们不知道“t”或“I”是什么意思)。所有依赖decltypes当前都被视为同一类型。
模板 < 类别名 我> 汽车 foo(I)-> 脱模 (内华达州) {}
模板 < 类别名 我>