SFINAE是否适用于功能体

Does SFINAE apply to function bodies?

本文关键字:功能 适用于 是否 SFINAE      更新时间:2023-10-16

我有以下示例代码:

class Serializable {};
class MyData : public Serializable {};
void GetData( Serializable& ) {}
template<typename T>
void GetData( T& data )
{
    std::istringstream s{"test"};
    s >> data;
}
int main()
{
    MyData d;
    GetData(d);
}

(现场样本(

根据重载解析规则,应首选非模板版本,因为基类的类型为 Serializable 。但是,我希望 SFINAE 在实例化重载解析时模板版本中出现错误时会启动(因为如果没有为类型定义>> 运算符,则不应考虑它(。

为什么即使不使用模板,它仍然失败?

根据重载解析规则,非模板版本应为 首选,因为基类的类型为 Serializable

差一点。[over.match.best]:

根据这些定义,一个可行的函数F1被定义为 比另一个可行的函数更好的函数 F2 对于所有参数 i, ICSi(F1( 不是比 ICSi(F2( 更糟糕的转换序列,然后

  • 对于某些参数 j,ICSj(F1( 是比 ICSj(F2( 更好的转换序列,或者,如果不是这样,
  • [...]
  • F1不是函数模板专用化,F2是函数模板专用化 [...]

这意味着,仅当函数模板的推导专用化需要的转换不优于普通函数所需的转换时,您的规则才适用。dSerializable& 的绑定比 d 与 MyData& 的绑定(这是专用化参数的类型(的转换更糟糕,[over.ics.ref]:

当引用类型的参数直接绑定 (8.5.3( 到 参数表达式,隐式转换序列是恒等式 转换,除非参数表达式的类型为 参数类型的派生类,在这种情况下为隐式 转换序列是派生到基础的转换 (13.3.3.1(。

但是,我希望SFINAE在 实例化以解决重载时的模板版本 (因为如果未为类型定义>>运算符,则不应 被考虑(。

SFINAE 不适用于函数模板的内容。[温度扣除]/8:

函数类型及其模板参数类型可能会导致 演绎失败。

因此,确实选择了函数模板的推导专用化,并在实例化其定义时导致编译器错误。