C ++模板函数重载解析 [英] C++ template functions overload resolution

查看:278
本文介绍了C ++模板函数重载解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

  #include< iostream> 

template< typename T>
void f(T){std :: cout< f(T)< std :: endl; }

template< typename T>
void f(bool){std :: cout< f(bool)<< std :: endl; }

int main()
{
f(true); //#1 prints f(T)
f< bool>(true); //#2 prints f(bool)
}

#1 线路呼叫 f(T),而#2 $ c> f(bool)。



为什么会发生?选择重载模板函数的规则是什么?



UPDATE



我理解,在第一次调用编译器只是无法推导 T ,而试图调用第二个函数,所以第一个选择。



在第二个调用中,第二个函数被认为是在gcc上更好的匹配,而第一个是在VS2013下选择的。谁在这里做正确的事?顺便说一句,我仍然对这个过程的完整描述感兴趣。

解决方案

未特殊化的函数模板也称为底层基本模板。基本模板可以是专门的。重载规则可以看到在不同情况下调用的规则是非常简单的,至少在高级别:




  • Nontemplate功能是一流的公民。


  • 如果选择了一个简单的非模板函数,它将匹配参数类型以及任何函数模板。没有一流的公民从中选择至少一样好,然后功能基础模板作为二等公民接下来咨询。哪个函数基础模板被选择取决于哪个匹配最好,是最专业的(重要注意:这种使用专门的奇怪地与模板专业化无关;它只是一个不幸的口语主义)根据一套公平奥秘规则:




    • 如果显然有一个最专业的函数基础模板,那么就会被使用。如果该基本模板恰好适用于所使用的类型,那么将使用专门化,否则将使用以正确类型实例化的基本模板。


    • Else(如你的情况)如果最专业的函数基础模板有一个关系,调用是不明确的,因为编译器无法确定哪个是更好的匹配。


    • 否则,如果没有功能基本模板





如果您要自定义功能基本模板,并希望该自定义参与重载分辨率(或者始终在完全匹配的情况下使用)使它成为一个简单的老功能,而不是专业化。



上面是从这个帖子 Herb Sutter,在突出显示的项目符号中您可以看到问题的根源



EDIT



如果您尝试(不要这么做)上述代码与Visual Studio 2012,您会得到


致命错误LNK1179:无效或损坏的文件:重复的COMDAT'?? $ f @ _N @@ YAX_N @ Z'


< blockquote>

这是这里解释的原因,因为


你做了一些无效C ++的诡计,它通过了编译器,但是你现在有一个无效的* .obj,它扼杀了链接器。


并且下面一行是

  f(true); //#1列印f(T)

/ p>

I have the following code:

#include <iostream>

template <typename T>
void f (T) { std::cout << "f(T)" << std::endl; }

template <typename T>
void f (bool) { std::cout << "f(bool)" << std::endl; }

int main ( )
{
    f(true);        // #1 prints f(T)
    f<bool>(true);  // #2 prints f(bool)
}

The #1 line calls f(T), while #2 line calls f(bool).

Why does this happen? And what are the rules for selecting an overloaded template function?

UPDATE

I understood that in the first call compiler is just unable to deduce T while trying to call the second function, so the first is chosen.

In the second call second function is considered a better match on gcc, while the first is chosen under VS2013. Who does the right thing here? By the way, I am still interested in the full description of the process.

解决方案

The unspecialized function templates are also called the underlying base templates. Base templates can be specialized. The overloading rules to see which ones get called in different situations, are pretty simple, at least at a high level:

  • Nontemplate functions are first-class citizens. A plain old nontemplate function that matches the parameter types as well as any function template will be selected over an otherwise-just-as-good function template.

  • If there are no first-class citizens to choose from that are at least as good, then function base templates as the second-class citizens get consulted next. Which function base template gets selected depends on which matches best and is the "most specialized" (important note: this use of "specialized" oddly enough has nothing to do with template specializations; it's just an unfortunate colloquialism) according to a set of fairly arcane rules:

    • If it's clear that there's one "most specialized" function base template, that one gets used. If that base template happens to be specialized for the types being used, the specialization will get used, otherwise the base template instantiated with the correct types will be used.

    • Else (as in your case) if there's a tie for the "most specialized" function base template, the call is ambiguous because the compiler can't decide which is a better match. The programmer will have to do something to qualify the call and say which one is wanted.

    • Else if there's no function base template that can be made to match, the call is bad and the programmer will have to fix the code.

If you want to customize a function base template and want that customization to participate in overload resolution (or, to always be used in the case of exact match), make it a plain old function, not a specialization. And, if you do provide overloads, avoid also providing specializations.

The above is an extract from this post by the Herb Sutter and in the highlighted bullet you can see the source of your problem

EDIT

If you try (don't do it) the above code with Visual Studio 2012, you get

fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '??$f@_N@@YAX_N@Z'

which, as explained here, is because

You did some "trickery" that is invalid C++, and it passed the compiler, but you now have an invalid *.obj, and it chokes the linker.

and the following line is to blame

f(true);        // #1 prints f(T)

so the ambiguity explained in the answer has no guarandeed resolution

这篇关于C ++模板函数重载解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆