我有以下代码:
#include <iostream> #include <vector> using namespace std; struct A{}; struct B: public A {}; template <typename T> void foo(const T& obj) { cerr << "Generic case"<< endl;} void foo(const A& a) { cerr << "Specific case" << endl; } int main() { vector<int> v; foo(v); B b; foo(b); A a; foo(a); }输出是
通用案例 通用案例 具体情况为什么没有为B对象选择foo(const A& a) ?
奇怪的是,如果我删除了模板化方法并且只是具有以下内容:
#include <iostream> #include <vector> struct A{}; struct B: public A {}; //template <typename T> //void foo(const T& obj) { cerr << "Generic case"<< endl;} void foo(const A& a) { cerr << "Specific case" << endl; } int main() { B b; foo(b); A a; foo(a); }代码编译,输出为:
Specific case Specific case为什么模板化方法的存在会产生这样的差异?
编辑:如何在存在模板化方法的情况下强制编译器为从A派生的类选择自由方法?
I have the following code:
#include <iostream> #include <vector> using namespace std; struct A{}; struct B: public A {}; template <typename T> void foo(const T& obj) { cerr << "Generic case"<< endl;} void foo(const A& a) { cerr << "Specific case" << endl; } int main() { vector<int> v; foo(v); B b; foo(b); A a; foo(a); }Output is
Generic case Generic case Specific caseWhy is it that foo(const A& a) is not being chosen for the B object ?
Curiously enough, if I removed the templated method and just have the following:
#include <iostream> #include <vector> struct A{}; struct B: public A {}; //template <typename T> //void foo(const T& obj) { cerr << "Generic case"<< endl;} void foo(const A& a) { cerr << "Specific case" << endl; } int main() { B b; foo(b); A a; foo(a); }The code compiles and the output is:
Specific case Specific caseWhy is the presence of the templated method making such a difference?
Edit: How can I force the compiler to choose the free method for classes derived from A in the presence of the templated method?
最满意答案
对foo(const B&)的调用不需要转换,模板实例化会产生这种转换,因此它是更好的匹配。
当编译器看到函数调用时,必须实例化每个基函数模板,并将其与每个正常函数一起包含在重载集中。 之后执行重载解析。 还有SFINAE,它允许实例化函数模板以导致错误(这样的函数不会被添加到过载集中)。 事实上,事情并非如此简单,但它应该给出一般情况。
关于你的编辑:只有一种方法可以调用。 还有什么可以作为输出?
No conversion is necessary for the call to foo(const B&) which the template instantiation yields thus it is the better match.
When a function call is seen by the compiler, every base function template has to be instantiated and is included in the overload set along with every normal function. After that overload resolution is performed. There is also SFINAE, which allows an instantiation of a function template to lead to an error (such a function would not be added to the overload set). Of course, things aren't really that simple, but it should give the general picture.
Regarding your edit: There is only one method to call. What else could there be as output?
更多推荐
发布评论