开发者

Explicit Instantiation

This was motivated by this article (page 开发者_JAVA百科5)

template<class T> 
T const &f(T const &a, T const &b){
    return (a > b ? a : b);
}

template int const &f<int>(int const &, int const &);

int main(){
    int x = 0, y = 0;
    short s = 0;
    f(x, y);     // OK
    f(x, s);     // Is this call well-formed?
}

Is the call 'f(x, s)' well-formed? I assumed that since the function template 'f' is explicitly instantiated, standard conversions would be applied and hence 'short s' would be converted to 'int' to match the call to the explicit specialization 'f<int>'. But it appears that this is ill-formed?

Which part of the Standard talks about the applicable rules in this context?


No, the call f(x, s) is not well-formed. Since you do not explicitly state the specialization to be used, the compiler uses argument deduction to attempt to instantiate the function template; this fails because x and s have different types so T is ambiguous.

The applicable rule is in the specification of the overload resolution process in 13.3.1:

In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way.

14.8.3/1 is also relevant:

For each function template, if the argument deduction and checking succeeds, the template arguments (deduced and/or explicit) are used to instantiate a single function template specialization which is added to the candidate functions set to be used in overload resolution. If, for a given function template, argument deduction fails, no such function is added to the set of candidate functions for that template.

The function template is explicitly instantiated for T = int, but the compiler doesn't know that it should use this instantiation until after it performs template argument deduction to determine what T should be.


The call f(x, s) is syntactically well-formed, but the compiler will not be able to deduce the template parameter T from it because is could a int or a short (because of the first and second arguments). Instantiating the template does not help, that only indicates the compiler to compile that specialization and add it to the generated object file.

If you want the call to cast s to a int automatically, use f<int>(x, s).


An explicitly instantiated specialization doesn't have any higher priority or preferential treatment. It simply exists in its entirety from the point of instantiation. Useful for libraries.

The compiler simply can't figure out which argument to convert, and gets stuck just as it would without the extra declaration.

By the way, if you return it a reference to an argument which was converted, it will be dangling once the temporary expires. If the arguments are references to different types, there is no way to properly form the return value.

Here is my updated min:

#include <type_traits>

template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
    return a < b? a : b;
}

 // enable_if< is_same< A, B > > the old, return-by-reference impl

int main() {
    int q = my_min( short(5), long(3) );
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜