C++ SFINAE是否适用于职能机构?

C++ SFINAE是否适用于职能机构?,c++,templates,language-lawyer,overload-resolution,upcasting,C++,Templates,Language Lawyer,Overload Resolution,Upcasting,我有以下示例代码: 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

我有以下示例代码:

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);
}
类可序列化{};
类MyData:public Serializable{};
void GetData(可序列化&){}
模板
无效GetData(T&data)
{
std::istringstreams{“test”};
s>>数据;
}
int main()
{
MyData d;
获取数据(d);
}
()

基于重载解析规则,应首选非模板版本,因为基类的类型为
可序列化
。但是,当模板版本为重载解析而实例化时出现错误时,我希望SFINAE能够启动(因为如果没有为类型定义>>运算符,则不应考虑它)

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

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

不完全是。[结束,比赛,最佳]:

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

  • 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是那样,
  • [……]
  • F1
    不是函数模板专用化,
    F2
    是函数模板专用化[…]
这意味着,只有当函数模板的推导专门化需要的转换并不比普通函数需要的转换好时,您的规则才适用。 将
d
绑定到
Serializable&
比将d绑定到
MyData&
(这是专门化的参数类型)的转换更糟糕,[over.ics.ref]:

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

然而,我希望SFINAE在测试中出现错误时能够发挥作用 为重载解析实例化模板时的模板版本 (因为如果未为类型定义>>运算符,则不应定义该运算符。) (将予以考虑)

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

在的直接上下文中,只有无效的类型和表达式 函数类型及其模板参数类型可导致 扣除失败


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

只有在完全匹配的情况下,才应首选非模板版本。看看如果你使用
MyData
而不是
Serializable
会发生什么。这里“专门化”一词的标准用法实际上是模板的“实例化”,对吗?因为在我看来,专门化是指当函数显式地为类型实现时。在我的例子中,我没有明确地专门化基本函数模板。@void.pointer似乎您混淆了术语。专门化是使用推导的模板参数实例化的函数。你说的是明确的专业化。