Does SFINAE apply to function bodies?

帅比萌擦擦* 提交于 2019-12-18 08:58:35

问题


I have the following sample code:

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);
}

(Live Sample)

Based on overload resolution rules, the non-template version should be preferred because the base class is of type Serializable. However, I expect SFINAE to kick in when there are errors in the template version when it is instantiated for overload resolution (because if the >> operator is not defined for a type, it should not be considered).

Why is it still failing even though the template won't be used?


回答1:


Based on overload resolution rules, the non-template version should be preferred because the base class is of type Serializable.

Not quite. [over.match.best]:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

  • for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
  • […]
  • F1 is not a function template specialization and F2 is a function template specialization […]

That means that only if the deduced specialization of the function template necessitates a conversion that isn't better than the conversion that the normal function necessitates, your rule applies. And the binding of d to Serializable& is a worse conversion than the binding of d to MyData& (which is the type of the parameter of the specialization), [over.ics.ref]:

When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion (13.3.3.1).

However, I expect SFINAE to kick in when there are errors in the template version when it is instantiated for overload resolution (because if the >> operator is not defined for a type, it should not be considered).

SFINAE doesn't apply for the content of a function template. [temp.deduct]/8:

Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.

Hence the deduced specialization of the function template is indeed chosen, and causes a compiler error while instantiating its definition.



来源:https://stackoverflow.com/questions/27301135/does-sfinae-apply-to-function-bodies

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!