为什么这个代码调用不同的模板函数在vs2005? [英] Why does this code call different template function in vs2005?

查看:118
本文介绍了为什么这个代码调用不同的模板函数在vs2005?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码是:

  #include< iostream> 
using namespace std;

//比较两个对象
template< typename T> void compare(const T& const T&){
cout<<T<< endl;
};
//比较两个序列中的元素
template< class U,class V> void compare(U,U,V){
cout<<UV<
};
//用于处理C风格字符串的纯函数
void compare(const char *,const char *){
cout<<普通<
};

int main(){

cout<<------------------------ -char * --------------------------<< endl;

char * c =a;
char * d =b;
compare(c,d);

cout<<------------------------- char [2] -------- -------------------<< endl;

char e [] =a;
char f [] =b;
compare(e,f);

系统(pause);
}

结果是:


------------------------- char * ------------- -------------



T



------ ------------------- char [2] -----------------------



普通


我的问题是:
为什么compare d)调用比较(const T& const T&)和compare(e,f)调用普通函数,即使两个函数的参数是char * s?

解决方案

看来VS2005可能错误地对待 e f 变量 const char * 类型。



考虑下面的代码:

  #include< iostream> 
using namespace std;

template< typename T> void compare(const T& const T&){
cout<< T:;
};

template< class U,class V> void compare(U,U,V){
cout< UV:;
};

void compare(const char *,const char *){
cout< 普通:;
};

int main(void){
char * c =a;
char * d =b;
compare(c,d);
cout<< < - char * \\\
;

char e [] =a;
char f [] =b;
compare(e,f);
cout<< < - char [] \ n;

const char g [] =a;
const char h [] =b;
compare(g,h);
cout<< < - const char [] \\\
;

return 0;
}

其输出:

  T:<  -  char * 
T:< - char []
普通:< - const char []






13.3过载解决的C ++ 03(部分号在C ++ 11中似乎没有变化,所以相同的注释适用于那里)指定如何选择使用哪个函数,我将尝试用(相对)简单的术语解释它,标准是一种干读。

基本上,一个候选函数的列表是基于函数是如何被实际调用的类/对象的成员函数,常规(无修饰)函数调用,通过指针调用等)。



然后, >可行函数基于参数计数提取。



然后,从可行函数中,基于最小隐式转换序列(参见 13.3.3 C ++ 03的最佳可行函数)。



用于从基于每个参数所需的隐式转换设置的可行列表中选择函数的成本。选择函数的成本是每个参数成本的总和,编译器将选择具有最小成本的函数。



如果发现两个函数具有相同的成本,则标准规定编译器应将其视为错误。



,如果你有一个函数,其中隐式转换发生在一个参数,它将优先于其中两个参数必须以相同的方式转换。



成本可以在下表的等级列中看到。

 排名转换
---- ----------
完全匹配不需要转换
Lvalue-to-rvalue转换
数组到指针转换
函数到指针转换
资格转换
促销积分促销
浮点促销
转换积分转换
浮点转换
浮动积分换算
指针转换
指针到成员转换
布尔转换

在转换成本相同的地方对于 F1 F2 (例如在您的情况下), F1 被认为更好,如果:


F1是非模板函数,F2是函数模板专用化。







但是,这不是整个故事,因为模板代码和非模板代码都是完全匹配的你会期望看到在所有情况下调用的非模板函数,而不是第三个。



这在标准中进一步讨论:答案在 13.3.3.2排序隐式转换序列。该部分规定,在某些条件下,除了之外,相同的排名将导致歧义 ,其中之一是:


标准转换序列S1是比标准转换序列S2更好的转换序列,如果(1)S1是S2的适当子序列(比较由13.3.3.1.1定义的规范形式的转换序列,排除任何Lvalue变换;同一性转换序列被认为是任何非同一性转换序列的子序列)...


模板版本的转换实际上是非模板版本(资格AND数组到指针转换)的正确子集(资格转换),正确的子集被认为具有较低的成本。



因此,它更喜欢前两种情况下的模板版本。在第三种情况下,唯一的转换是非模板版本的数组到指针和模板版本的限定,因此没有任何方向的子集,它更喜欢基于上述规则的非模板版本,在排名表下)。


The code is:

#include <iostream>
using namespace std;

// compares two objects
template <typename T> void compare(const T&, const T&){
    cout<<"T"<<endl;
};
// compares elements in two sequences
template <class U, class V> void compare(U, U, V){
    cout<<"UV"<<endl;
};
// plain functions to handle C-style character strings
void compare(const char*, const char*){
    cout<<"ordinary"<<endl;
};

int main() {

    cout<<"-------------------------char* --------------------------"<< endl;

    char* c="a";
    char* d="b";
    compare(c,d);

cout<<"------------------------- char [2]---------------------------"<< endl;

    char e[]= "a";
    char f[]="b";
    compare(e,f);

    system("pause");
}

The result is:

-------------------------char* --------------------------

T

------------------------- char [2]-----------------------

ordinary

And my question is: Why does compare(c,d) call compare(const T&, const T&) and compare(e,f) call the ordinary function even though the arguments of the two functions are char*s?

解决方案

It appears that VS2005 may be erroneously treating the e and f variables as const char * types.

Consider the following code:

#include <iostream>
using namespace std;

template <typename T> void compare (const T&, const T&) {
    cout << "T:        ";
};

template <class U, class V> void compare (U, U, V) {
    cout << "UV:       ";
};

void compare (const char*, const char*) {
    cout << "ordinary: ";
};

int main (void) {
    char* c = "a";
    char* d = "b";
    compare (c,d);
    cout << "<- char *\n";

    char e[] = "a";
    char f[] = "b";
    compare (e,f);
    cout << "<- char []\n";

    const char g[] = "a";
    const char h[] = "b";
    compare (g,h);
    cout << "<- const char []\n";

    return 0;
}

which outputs:

T:        <- char *
T:        <- char []
ordinary: <- const char []


Section 13.3 Overload resolution of C++03 (section numbers appear to be unchanged in C++11 so the same comments apply there) specifies how to select which function is used and I'll try to explain it in (relatively) simple terms, given that the standard is rather a dry read.

Basically, a list of candidate functions is built based on how the function is actually being called (as a member function of an class/object, regular (unadorned) function calls, calls via a pointer and so on).

Then, out of those, a list of viable functions is extracted based on argument counts.

Then, from the viable functions, the best fit function is selected based on the idea of a minimal implicit conversion sequence (see 13.3.3 Best viable function of C++03).

In essence, there is a "cost" for selecting a function from the viable list that is set based on the implicit conversions required for each argument. The cost of selecting the function is the sum of the costs for each individual argument to that function, and the compiler will chose the function with the minimal cost.

If two functions are found with the same cost, the standard states the the compiler should treat it as an error.

So, if you have a function where an implicit conversion happens to one argument, it will be preferred over one where two arguments have to be converted in that same way.

The "cost" can be see in the table below in the Rank column. An exact match has less cost than promotion, which has less cost than conversion.

Rank                 Conversion
----                 ----------
Exact match          No conversions required
                     Lvalue-to-rvalue conversion
                     Array-to-pointer conversion
                     Function-to-pointer conversion
                     Qualification conversion
Promotion            Integral promotions
                     Floating point promotions
Conversion           Integral conversion
                     Floating point conversions
                     Floating-integral conversions
                     Pointer conversions
                     Pointer-to-member conversions
                     Boolean conversions

In places where the conversion cost is identical for functions F1 and F2 (such as in your case), F1 is considered better if:

F1 is a non-template function and F2 is a function template specialization.


However, that's not the whole story since the template code and non-template code are all exact matches hence you would expect to see the non-template function called in all cases rather than just the third.

That's covered further on in the standard: The answer lies in section 13.3.3.2 Ranking implicit conversion sequences. That section states that an identical rank would result in ambiguity except under certain conditions, one of which is:

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if (1) S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) ...

The conversions for the template version are actually a proper subset (qualification conversion) of the non-template version (qualification AND array-to-pointer conversions), and proper subsets are deemed to have a lower cost.

Hence it prefers the template version in the first two cases. In the third case, the only conversions are array-to-pointer for the non-template version and qualification for the template version, hence there's no subset in either direction, and it prefers the non-template version based on the rule I mentioned above, under the ranking table).

这篇关于为什么这个代码调用不同的模板函数在vs2005?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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