Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

c++ - Does SFINAE apply to function bodies?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...