SFINAE是否适用于职能机构?

voi*_*ter 3 c++ templates upcasting language-lawyer overload-resolution

我有以下示例代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

现场样本

基于重载解析规则,应首选非模板版本,因为基类是type Serializable。但是,我希望在实例化模板版本以进行重载解析时,模板版本中有错误时,SFINAE会启动(因为如果未为类型定义>>运算符,则不应考虑)。

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

Col*_*mbo 5

基于重载解析规则,应首选非模板版本,因为基类是type Serializable

不完全的。[over.match.best]:

给定这些定义,如果对于所有自变量i,ICSi(F1)的转换顺序都不比ICSi(F2)差,则将一个可行函数F1定义为比另一个可行函数更好的函数F2,然后

  • 对于某些参数j,ICSj(F1)比ICSj(F2)更好的转换顺序,或者,如果不是,
  • […]
  • F1不是功能模板专业化,F2而是功能模板专业化[…]

这意味着只有在推导的功能模板的专业化需要进行的转换不比普通函数进行的转换更好的情况下,您的规则才适用。与dto Serializable&的绑定比与d的绑定MyData&(这是专业化参数的类型)更糟糕的转换,[over.ics.ref]:

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

但是,我希望当实例化模板版本以进行重载解析时,如果模板版本中存在错误,SFINAE就会启动(因为如果未为类型定义>>运算符,则不应考虑它)。

SFINAE不适用于功能模板的内容。[扣减] / 8:

只有在函数类型及其模板参数类型的直接上下文中无效的类型和表达式才能导致推论失败。

因此,确实选择了推导的功能模板的专业化,并且在实例化其定义时会导致编译器错误。